Fix oss-fuzz #61712: assertion failure with error handler during binary op

Because the error handler is invoked after the property is updated,
the error handler has the opportunity to remove it before the property
is returned.

Switching the order around fixes this issue. The comments mention that
the current ordering prevents overwriting the EG(std_property_info)
field in the error handler. EG(std_property_info) no longer exists as it
was removed in 7471c217. Back then a global was used to store the
returned property info, but as this is no longer the case there is no
longer a need to protect against overwriting a global.

Closes GH-12062.
This commit is contained in:
Niels Dossche 2023-08-27 17:46:10 +02:00
parent 1413787884
commit a3a3964497
3 changed files with 23 additions and 3 deletions

2
NEWS
View File

@ -8,6 +8,8 @@ PHP NEWS
(Jakub Zelenka)
. Fixed bug GH-11790 (On riscv64 require libatomic if actually needed).
(Jeremie Courreges-Anglas)
. Fixed oss-fuzz #61712 (assertion failure with error handler during binary
op). (nielsdos)
- DOM:
. Fixed GH-11952 (Confusing warning when blocking entity loading via

View File

@ -0,0 +1,20 @@
--TEST--
OSS-Fuzz #61712 (assertion failure with error handler during binary op)
--FILE--
<?php
#[AllowDynamicProperties]
class C {
function error($_, $msg) {
echo $msg, "\n";
unset($this->a);
}
}
$c = new C;
set_error_handler([$c, 'error']);
$c->a %= 10;
var_dump($c->a);
?>
--EXPECT--
Undefined property: C::$a
int(0)

View File

@ -1160,12 +1160,10 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam
if (UNEXPECTED(!zobj->properties)) {
rebuild_object_properties(zobj);
}
retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
/* Notice is thrown after creation of the property, to avoid EG(std_property_info)
* being overwritten in an error handler. */
if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
}
retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
}
} else if (zobj->ce->__get == NULL) {
retval = &EG(error_zval);