Commit f38f74521b6 for php.net
commit f38f74521b61f4a7e74d0124f557fa1d898bf0e2
Author: Ilija Tovilo <ilija.tovilo@me.com>
Date: Mon Jan 19 15:47:03 2026 +0100
Fix lazy proxy bailing __clone assertion
When __clone of the underlying object fails with a bailout, ZEND_ASSERT(res ==
SUCCESS) in zend_lazy_object_del_info() will fail because the info has not been
registered yet.
Only copy OBJ_EXTRA_FLAGS once the info has been successfully registered.
Fixes GH-20905
Closes GH-20975
diff --git a/NEWS b/NEWS
index 06ebe601478..80b69c11cf8 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ PHP NEWS
backing value). (ilutov)
. Fix OSS-Fuzz #438780145 (Nested finally with repeated return type check may
uaf). (ilutov)
+ . Fixed bug GH-20905 (Lazy proxy bailing __clone assertion). (ilutov)
- Date:
. Update timelib to 2022.16. (Derick)
diff --git a/Zend/tests/lazy_objects/gh20905.phpt b/Zend/tests/lazy_objects/gh20905.phpt
new file mode 100644
index 00000000000..48a1360c0a9
--- /dev/null
+++ b/Zend/tests/lazy_objects/gh20905.phpt
@@ -0,0 +1,22 @@
+--TEST--
+GH-20905: Lazy proxy bailing __clone assertion
+--FILE--
+<?php
+
+function test() {
+ function f() {}
+}
+
+class A {
+ public $_;
+ public function __clone() {
+ test();
+ }
+}
+
+test();
+clone (new ReflectionClass(A::class))->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 d1b950160e1..bf76f6e88fe 100644
--- a/Zend/zend_lazy_objects.c
+++ b/Zend/zend_lazy_objects.c
@@ -744,12 +744,11 @@ zend_object *zend_lazy_object_clone(zend_object *old_obj)
}
}
- OBJ_EXTRA_FLAGS(new_proxy) = OBJ_EXTRA_FLAGS(old_obj);
-
zend_lazy_object_info *new_info = emalloc(sizeof(*info));
*new_info = *info;
new_info->u.instance = zend_objects_clone_obj(info->u.instance);
+ OBJ_EXTRA_FLAGS(new_proxy) = OBJ_EXTRA_FLAGS(old_obj);
zend_lazy_object_set_info(new_proxy, new_info);
return new_proxy;