mirror of
https://github.com/php/php-src.git
synced 2024-11-23 01:44:06 +08:00
Lazy objects: Update class constants earlier
If a lazy object is created for a class whose constants can not be updated, then we have created an instance of a non-instantiable class. This breaks the expectations of clone. Here I ensure that a class has its constants updated before creating a lazy instance of it. Fixes OSS-Fuzz #71407 Closes GH-15856
This commit is contained in:
parent
30dd291628
commit
64081d1380
2
NEWS
2
NEWS
@ -17,6 +17,8 @@ PHP NEWS
|
||||
. Fixed bug GH-16371 (Assertion failure in Zend/zend_weakrefs.c:646). (Arnaud)
|
||||
. Fixed missing error when adding asymmetric visibility to static properties.
|
||||
(ilutov)
|
||||
. Fixed bug OSS-Fuzz #71407 (Null-dereference WRITE in
|
||||
zend_lazy_object_clone). (Arnaud)
|
||||
|
||||
- Curl:
|
||||
. Fixed bug GH-16302 (CurlMultiHandle holds a reference to CurlHandle if
|
||||
|
@ -1,27 +0,0 @@
|
||||
--TEST--
|
||||
Lazy objects: Class constants are updated before initialization
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class C {
|
||||
public stdClass $a = FOO;
|
||||
}
|
||||
|
||||
$reflector = new ReflectionClass(C::class);
|
||||
$c = $reflector->newLazyGhost(function () { });
|
||||
|
||||
function f() {
|
||||
define('FOO', new stdClass);
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
try {
|
||||
var_dump($c->a);
|
||||
} catch (\Error $e) {
|
||||
printf("%s: %s\n", $e::class, $e->getMessage());
|
||||
}
|
||||
|
||||
--EXPECTF--
|
||||
object(stdClass)#%d (0) {
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
Lazy objects: Class constants are updated before initialization: update constant failure
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class C {
|
||||
public C $a = FOO;
|
||||
}
|
||||
|
||||
$reflector = new ReflectionClass(C::class);
|
||||
$c = $reflector->newLazyGhost(function () { });
|
||||
|
||||
function f() {
|
||||
define('FOO', new stdClass);
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
try {
|
||||
var_dump($c->a);
|
||||
} catch (\Error $e) {
|
||||
printf("%s: %s\n", $e::class, $e->getMessage());
|
||||
}
|
||||
|
||||
--EXPECT--
|
||||
TypeError: Cannot assign stdClass to property C::$a of type C
|
22
Zend/tests/lazy_objects/oss_fuzz_71407.phpt
Normal file
22
Zend/tests/lazy_objects/oss_fuzz_71407.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
oss-fuzz #71407
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class C {
|
||||
public $x=x;
|
||||
}
|
||||
|
||||
$reflector = new ReflectionClass(C::class);
|
||||
|
||||
try {
|
||||
$obj = $reflector->newLazyGhost(function() {});
|
||||
clone $obj;
|
||||
} catch (Error $e) {
|
||||
printf("%s: %s\n", $e::class, $e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Error: Undefined constant "x"
|
@ -259,6 +259,13 @@ ZEND_API zend_object *zend_object_make_lazy(zend_object *obj,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(!(reflection_ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
|
||||
if (UNEXPECTED(zend_update_class_constants(reflection_ce) != SUCCESS)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
obj = zend_objects_new(reflection_ce);
|
||||
|
||||
for (int i = 0; i < obj->ce->default_properties_count; i++) {
|
||||
@ -373,12 +380,7 @@ ZEND_API zend_object *zend_lazy_object_mark_as_initialized(zend_object *obj)
|
||||
|
||||
zend_class_entry *ce = obj->ce;
|
||||
|
||||
if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
|
||||
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ZEND_ASSERT(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED);
|
||||
|
||||
zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce);
|
||||
zval *properties_table = obj->properties_table;
|
||||
@ -568,12 +570,7 @@ ZEND_API zend_object *zend_lazy_object_init(zend_object *obj)
|
||||
|
||||
zend_class_entry *ce = obj->ce;
|
||||
|
||||
if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
|
||||
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ZEND_ASSERT(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED);
|
||||
|
||||
if (zend_object_is_lazy_proxy(obj)) {
|
||||
return zend_lazy_object_init_proxy(obj);
|
||||
|
Loading…
Reference in New Issue
Block a user