Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Zend/tests/clone_clone_method_declares_function.phpt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
Lazy objects: clone does not assert when __clone() declares a function causing a fatal error
--FILE--
<?php

// Regression test for GH-20905:
// When __clone() declares a function that was already declared (triggering E_ERROR
// and bailout), del_info() was called during shutdown on an object whose info entry
// had already been removed, causing an assertion failure in debug builds.

function f() {}

class A {
public stdClass $p;

public function __construct()
{
$this->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
2 changes: 1 addition & 1 deletion Zend/zend_lazy_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading