From: Nikita Popov Date: Mon, 3 Aug 2020 08:34:39 +0000 (+0200) Subject: Fix bug #79925 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bb8b95be636528ebfc6f00b2153254d06e27ead9;p=php Fix bug #79925 If the expected return type of a magic method is "object", we also need to allow class types and "static" to comply with covariance. --- diff --git a/Zend/tests/magic_methods_021.phpt b/Zend/tests/magic_methods_021.phpt new file mode 100644 index 0000000000..fd3e7fa9d0 --- /dev/null +++ b/Zend/tests/magic_methods_021.phpt @@ -0,0 +1,21 @@ +--TEST-- +__set_state return type should support covariance +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c2f887a5bc..9906d7b423 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2063,10 +2063,19 @@ static void zend_check_magic_method_arg_type(uint32_t arg_num, const zend_class_ static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type) { - if ( - (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) - && (ZEND_TYPE_FULL_MASK(fptr->common.arg_info[-1].type) & ~return_type) - ) { + if (!(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { + /* For backwards compatibility reasons, do not enforce the return type if it is not set. */ + return; + } + + bool has_class_type = ZEND_TYPE_HAS_CLASS(fptr->common.arg_info[-1].type); + uint32_t extra_types = ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & ~return_type; + if (extra_types & MAY_BE_STATIC) { + extra_types &= ~MAY_BE_STATIC; + has_class_type = 1; + } + + if (extra_types || (has_class_type && return_type != MAY_BE_OBJECT)) { zend_error(error_type, "%s::%s(): Return type must be %s when declared", ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name), ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(return_type))));