Skip to content

Commit 69152a2

Browse files
Fix GH-20905: assertion in zend_lazy_object_del_info during unclean shutdown
1 parent 7e16d4e commit 69152a2

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Lazy objects: clone does not assert when __clone() declares a function causing a fatal error
3+
--FILE--
4+
<?php
5+
6+
// Regression test for GH-20905:
7+
// When __clone() declares a function that was already declared (triggering E_ERROR
8+
// and bailout), del_info() was called during shutdown on an object whose info entry
9+
// had already been removed, causing an assertion failure in debug builds.
10+
11+
function f() {}
12+
13+
class A {
14+
public stdClass $p;
15+
16+
public function __construct()
17+
{
18+
$this->p = new stdClass;
19+
}
20+
21+
public function __clone()
22+
{
23+
// Redeclaring an already-declared function triggers E_ERROR -> bailout.
24+
// The lazy object machinery must not assert during the resulting shutdown.
25+
function f() {}
26+
}
27+
}
28+
29+
$r = new ReflectionClass(A::class);
30+
clone $r->newLazyProxy(fn() => new A);
31+
?>
32+
--EXPECTF--
33+
Fatal error: Cannot redeclare function f() (previously declared in %s:%d) in %s on line %d

Zend/zend_lazy_objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ zend_lazy_object_flags_t zend_lazy_object_get_flags(const zend_object *obj)
162162
void zend_lazy_object_del_info(const zend_object *obj)
163163
{
164164
zend_result res = zend_hash_index_del(&EG(lazy_objects_store).infos, obj->handle);
165-
ZEND_ASSERT(res == SUCCESS);
165+
ZEND_ASSERT(res == SUCCESS || CG(unclean_shutdown));
166166
}
167167

168168
bool zend_lazy_object_decr_lazy_props(const zend_object *obj)

0 commit comments

Comments
 (0)