From 69152a2ac3e0cbc8e7e2ac7bb81884a171bd2a95 Mon Sep 17 00:00:00 2001 From: viktor Date: Sat, 14 Mar 2026 21:23:16 +0200 Subject: [PATCH] Fix GH-20905: assertion in zend_lazy_object_del_info during unclean shutdown --- ...ne_clone_method_declares_function.phpt.php | 33 +++++++++++++++++++ Zend/zend_lazy_objects.c | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/clone_clone_method_declares_function.phpt.php diff --git a/Zend/tests/clone_clone_method_declares_function.phpt.php b/Zend/tests/clone_clone_method_declares_function.phpt.php new file mode 100644 index 0000000000000..1f50b8a09e151 --- /dev/null +++ b/Zend/tests/clone_clone_method_declares_function.phpt.php @@ -0,0 +1,33 @@ +--TEST-- +Lazy objects: clone does not assert when __clone() declares a function causing a fatal error +--FILE-- +p = new stdClass; + } + + public function __clone() + { + // Redeclaring an already-declared function triggers E_ERROR -> bailout. + // The lazy object machinery must not assert during the resulting shutdown. + function f() {} + } +} + +$r = new ReflectionClass(A::class); +clone $r->newLazyProxy(fn() => new A); +?> +--EXPECTF-- +Fatal error: Cannot redeclare function f() (previously declared in %s:%d) in %s on line %d diff --git a/Zend/zend_lazy_objects.c b/Zend/zend_lazy_objects.c index e88ecf9fbe657..97fc7ff0ce2c7 100644 --- a/Zend/zend_lazy_objects.c +++ b/Zend/zend_lazy_objects.c @@ -162,7 +162,7 @@ zend_lazy_object_flags_t zend_lazy_object_get_flags(const zend_object *obj) void zend_lazy_object_del_info(const zend_object *obj) { zend_result res = zend_hash_index_del(&EG(lazy_objects_store).infos, obj->handle); - ZEND_ASSERT(res == SUCCESS); + ZEND_ASSERT(res == SUCCESS || CG(unclean_shutdown)); } bool zend_lazy_object_decr_lazy_props(const zend_object *obj)