@@ -286,7 +286,7 @@ int _check_inherited_arg_info(
286286 } else {
287287 /* todo: delay to runtime. How? */
288288 /* Don't break bug62441! */
289- code = 0 ;
289+ code = -1 ;
290290 }
291291 } else {
292292 code = 0 ;
@@ -333,11 +333,7 @@ int _check_inherited_return_type(
333333 return 0 ;
334334 }
335335
336- if (!_check_inherited_arg_info (fe , fe_arg_info , proto , proto_arg_info , COVARIANT )) {
337- return 0 ;
338- }
339-
340- return 1 ;
336+ return _check_inherited_arg_info (fe , fe_arg_info , proto , proto_arg_info , COVARIANT );
341337}
342338
343339static
@@ -365,7 +361,7 @@ int _check_inherited_parameter_type(
365361}
366362/* }}} */
367363
368- static zend_bool zend_do_perform_implementation_check (const zend_function * fe , const zend_function * proto ) /* {{{ */
364+ static int zend_do_perform_implementation_check (const zend_function * fe , const zend_function * proto ) /* {{{ */
369365{
370366 uint32_t i , num_args ;
371367
@@ -2000,6 +1996,72 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent)
20001996}
20011997/* }}} */
20021998
1999+ ZEND_API void zend_verify_variance (zend_class_entry * ce ) /* {{{ */
2000+ {
2001+ // todo: name? "verify" typically means something else
2002+ // todo: de-duplicate all this
2003+ zend_function * child ;
2004+ ZEND_ASSERT (ce -> ce_flags & ZEND_ACC_LINKED );
2005+
2006+ ZEND_HASH_FOREACH_PTR (& ce -> function_table , child ) {
2007+ zend_function * parent = child -> common .prototype ;
2008+ /* If the parenttype method is private do not enforce a signature */
2009+ if (parent && !(parent -> common .fn_flags & ZEND_ACC_PRIVATE )) {
2010+ uint32_t i , num_args ;
2011+
2012+ /* Checks for constructors only if they are declared in an interface,
2013+ * or explicitly marked as abstract
2014+ */
2015+ if ((ce -> constructor == child )
2016+ && ((parent -> common .scope -> ce_flags & ZEND_ACC_INTERFACE ) == 0
2017+ && (parent -> common .fn_flags & ZEND_ACC_ABSTRACT ) == 0 ))
2018+ {
2019+ continue ;
2020+ }
2021+
2022+ /* Check return type compatibility, but only if the prototype already
2023+ * specifies a return type. Adding a new return type is always valid. */
2024+ if (parent -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) {
2025+ int check = _check_inherited_return_type (
2026+ child , child -> common .arg_info - 1 ,
2027+ parent , parent -> common .arg_info - 1 );
2028+ if (check < 0 ) {
2029+ zend_error_noreturn (E_ERROR , "Bad return!" );
2030+ }
2031+ }
2032+
2033+ num_args = parent -> common .num_args ;
2034+ if (parent -> common .fn_flags & ZEND_ACC_VARIADIC ) {
2035+ num_args ++ ;
2036+ if (child -> common .num_args >= parent -> common .num_args ) {
2037+ num_args = child -> common .num_args ;
2038+ if (child -> common .fn_flags & ZEND_ACC_VARIADIC ) {
2039+ num_args ++ ;
2040+ }
2041+ }
2042+ }
2043+
2044+ for (i = 0 ; i < num_args ; i ++ ) {
2045+ zend_arg_info * child_arg_info = & child -> common .arg_info [i ];
2046+ zend_arg_info * parent_arg_info = (i < parent -> common .num_args )
2047+ ? & parent -> common .arg_info [i ]
2048+ : & parent -> common .arg_info [parent -> common .num_args ];
2049+
2050+ int check = _check_inherited_parameter_type (
2051+ child , child_arg_info ,
2052+ parent , parent_arg_info );
2053+
2054+ if (check < 0 ) {
2055+ zend_error_noreturn (E_ERROR , "Bad arg!" );
2056+ }
2057+ }
2058+
2059+ }
2060+ } ZEND_HASH_FOREACH_END ();
2061+
2062+ }
2063+ /* }}} */
2064+
20032065/*
20042066 * Local variables:
20052067 * tab-width: 4
0 commit comments