From df1c218bb313ed26b794b8655933d8e3c8e54806 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 20 Sep 2026 00:37:35 +0200 Subject: [PATCH] Fix OSS-Fuzz #536440507: Immutable class incorrect assertion For immutable classes, the flag for updated constants lives on the mutable part (see zend_update_class_constants). That means the assertion is bogus and can be replaced with a more complex check via a helper function. For the case where we perform the flags check, but not as an assertion but as a proper check, deferring to zend_update_class_constants() is enough because it already checks the flags correctly itself. --- .../lazy_objects/oss_fuzz_536440507.phpt | 21 ++++++++++++++ Zend/zend_lazy_objects.c | 28 ++++++++++++++----- 2 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 Zend/tests/lazy_objects/oss_fuzz_536440507.phpt diff --git a/Zend/tests/lazy_objects/oss_fuzz_536440507.phpt b/Zend/tests/lazy_objects/oss_fuzz_536440507.phpt new file mode 100644 index 000000000000..02a1fcc69342 --- /dev/null +++ b/Zend/tests/lazy_objects/oss_fuzz_536440507.phpt @@ -0,0 +1,21 @@ +--TEST-- +OSS-Fuzz #536440507 (Immutable class incorrect assertion) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +newLazyGhost(function ($obj) {}); +var_dump($o->b); + +?> +--EXPECTF-- +Deprecated: Implicit conversion from float 3.4028236692093845E+32 to int loses precision in %s on line %d +int(%s) diff --git a/Zend/zend_lazy_objects.c b/Zend/zend_lazy_objects.c index 59c8ec36a9b8..12958abfb242 100644 --- a/Zend/zend_lazy_objects.c +++ b/Zend/zend_lazy_objects.c @@ -179,6 +179,18 @@ bool zend_lazy_object_decr_lazy_props(zend_object *obj) return info->lazy_properties_count == 0; } +/* See zend_update_class_constants(). */ +static zend_always_inline bool zend_class_constants_are_updated(const zend_class_entry *ce) { + if (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) { + return true; + } + if (ZEND_MAP_PTR(ce->mutable_data)) { + const zend_class_mutable_data *mutable_data = ZEND_MAP_PTR_GET_IMM(ce->mutable_data); + return mutable_data && (mutable_data->ce_flags & ZEND_ACC_CONSTANTS_UPDATED); + } + return false; +} + /** * Making objects lazy */ @@ -259,11 +271,9 @@ 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; - } + if (UNEXPECTED(zend_update_class_constants(reflection_ce) != SUCCESS)) { + ZEND_ASSERT(EG(exception)); + return NULL; } obj = zend_objects_new(reflection_ce); @@ -383,7 +393,9 @@ ZEND_API zend_object *zend_lazy_object_mark_as_initialized(zend_object *obj) zend_class_entry *ce = obj->ce; - ZEND_ASSERT(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED); +#if ZEND_DEBUG + ZEND_ASSERT(zend_class_constants_are_updated(ce)); +#endif zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce); zval *properties_table = obj->properties_table; @@ -579,7 +591,9 @@ ZEND_API zend_object *zend_lazy_object_init(zend_object *obj) zend_class_entry *ce = obj->ce; - ZEND_ASSERT(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED); +#if ZEND_DEBUG + ZEND_ASSERT(zend_class_constants_are_updated(ce)); +#endif if (zend_object_is_lazy_proxy(obj)) { return zend_lazy_object_init_proxy(obj);