mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Fix GH-17736: Assertion failure zend_reference_destroy()
The cache slot for FETCH_OBJ_W in function `test` is primed with the class for C. The next call uses a simplexml instance and reuses the same cache slot. simplexml's get_property_ptr handler does not use the cache slot, so the old values remain in the cache slot. When `zend_handle_fetch_obj_flags` is called this is not guarded by a check for the class entry. So we end up using the prop_info from the property C::$a instead of the simplexml property. This patch adds a reset to the cache slots in the property address fetch code and also in the extensions with a non-standard reference handler. This keeps the run time cache consistent and avoids the issue without complicating the fast paths. Closes GH-17739.
This commit is contained in:
parent
6bb56fe0cf
commit
ce8ab5f16a
11 changed files with 37 additions and 0 deletions
2
NEWS
2
NEWS
|
@ -2,6 +2,8 @@ PHP NEWS
|
|||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? ????, PHP 8.3.19
|
||||
|
||||
- Treewide:
|
||||
. Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos)
|
||||
|
||||
27 Feb 2025, PHP 8.3.18RC1
|
||||
|
||||
|
|
|
@ -3232,6 +3232,9 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else if (prop_op_type == IS_CONST) {
|
||||
/* CE mismatch, make cache slot consistent */
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
}
|
||||
|
||||
/* Pointer on property callback is required */
|
||||
|
|
|
@ -4399,6 +4399,7 @@ static zval *date_interval_get_property_ptr_ptr(zend_object *object, zend_string
|
|||
zend_string_equals_literal(name, "days") ||
|
||||
zend_string_equals_literal(name, "invert") ) {
|
||||
/* Fallback to read_property. */
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
ret = NULL;
|
||||
} else {
|
||||
ret = zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
|
||||
|
|
|
@ -303,6 +303,7 @@ static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, in
|
|||
return zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
|
||||
}
|
||||
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2495,6 +2495,7 @@ static zval *pdo_row_get_property_ptr_ptr(zend_object *object, zend_string *name
|
|||
ZEND_IGNORE_VALUE(type);
|
||||
ZEND_IGNORE_VALUE(cache_slot);
|
||||
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -635,6 +635,8 @@ static zval *sxe_property_get_adr(zend_object *object, zend_string *zname, int f
|
|||
SXE_ITER type;
|
||||
zval member;
|
||||
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
|
||||
sxe = php_sxe_fetch_object(object);
|
||||
GET_NODE(sxe, node);
|
||||
if (UNEXPECTED(!node)) {
|
||||
|
|
20
ext/simplexml/tests/gh17736.phpt
Normal file
20
ext/simplexml/tests/gh17736.phpt
Normal file
|
@ -0,0 +1,20 @@
|
|||
--TEST--
|
||||
GH-17736 (Assertion failure zend_reference_destroy())
|
||||
--EXTENSIONS--
|
||||
simplexml
|
||||
--FILE--
|
||||
<?php
|
||||
$o1 = new SimpleXMLElement('<a/>');
|
||||
class C {
|
||||
public int $a = 1;
|
||||
}
|
||||
function test($obj) {
|
||||
$ref =& $obj->a;
|
||||
}
|
||||
$obj = new C;
|
||||
test($obj);
|
||||
test($o1);
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
|
@ -1861,6 +1861,7 @@ static zval *php_snmp_get_property_ptr_ptr(zend_object *object, zend_string *nam
|
|||
return zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
|
||||
}
|
||||
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -844,6 +844,8 @@ static zval *spl_array_get_property_ptr_ptr(zend_object *object, zend_string *na
|
|||
|
||||
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
|
||||
&& !zend_std_has_property(object, name, ZEND_PROPERTY_EXISTS, NULL)) {
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
|
||||
/* If object has offsetGet() overridden, then fallback to read_property,
|
||||
* which will call offsetGet(). */
|
||||
zval member;
|
||||
|
|
|
@ -121,6 +121,8 @@ zval *xmlreader_get_property_ptr_ptr(zend_object *object, zend_string *name, int
|
|||
zval *retval = NULL;
|
||||
xmlreader_prop_handler *hnd = NULL;
|
||||
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
|
||||
obj = php_xmlreader_fetch_object(object);
|
||||
|
||||
if (obj->prop_handler != NULL) {
|
||||
|
|
|
@ -890,6 +890,8 @@ static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name
|
|||
zval *retval = NULL;
|
||||
zip_prop_handler *hnd = NULL;
|
||||
|
||||
cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
|
||||
|
||||
obj = php_zip_fetch_object(object);
|
||||
|
||||
if (obj->prop_handler != NULL) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue