diff --git a/NEWS b/NEWS index 5ea9ecbafb0b..046b49c3483c 100644 --- a/NEWS +++ b/NEWS @@ -139,6 +139,11 @@ PHP NEWS . Fixed a crash in readline_info() when completion_append_character contains a non-ASCII byte. (Weilin Du) +- Reflection: + . Fixed bug GH-24729 (Use-after-free in + ReflectionClass::setStaticPropertyValue() when the old value's destructor + unbinds the property). (Lazizbek Ergashev) + - SAPI: . Fixed infinite loop in sapi_header_op() for headers of 4 GiB or more. (Martin Mirchev) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 2c94a6e80d18..ae696e762b8c 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4439,21 +4439,12 @@ ZEND_METHOD(ReflectionClass, setStaticPropertyValue) RETURN_THROWS(); } - if (Z_ISREF_P(variable_ptr)) { - zend_reference *ref = Z_REF_P(variable_ptr); - variable_ptr = Z_REFVAL_P(variable_ptr); - - if (!zend_verify_ref_assignable_zval(ref, value, 0)) { - return; - } - } - if (ZEND_TYPE_IS_SET(prop_info->type) && !zend_verify_property_type(prop_info, value, 0)) { return; } - zval_ptr_dtor(variable_ptr); - ZVAL_COPY(variable_ptr, value); + Z_TRY_ADDREF_P(value); + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, 0); } /* }}} */ diff --git a/ext/reflection/tests/gh24729.phpt b/ext/reflection/tests/gh24729.phpt new file mode 100644 index 000000000000..beacb476328b --- /dev/null +++ b/ext/reflection/tests/gh24729.phpt @@ -0,0 +1,34 @@ +--TEST-- +GH-24729 (Use-after-free in ReflectionClass::setStaticPropertyValue() when the old value's destructor unbinds the property) +--FILE-- +setStaticPropertyValue('x', str_repeat('A', 64)); +var_dump(A::$x); + +class B { public static string $x = ''; } +class S { + public function __toString(): string { + unset($GLOBALS['w']); + $z = 'z'; + B::$x = &$z; + return str_repeat('B', 8); + } +} +$w = 'old'; +B::$x = &$w; +(new ReflectionClass('B'))->setStaticPropertyValue('x', new S); +var_dump(B::$x); +?> +--EXPECT-- +int(1) +string(8) "BBBBBBBB"