symfony / symfony/php-ext-deepclone
deepclone_to_array(): loses initializer of uninitialized PHP lazy ghost objects
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 17
- Forks
- 3
- PR merge metrics
- No merged PRs in 30d
Description
Title
deepclone_to_array() loses initializer of uninitialized PHP lazy ghost objects
Description
When an uninitialized native PHP lazy ghost object is passed to deepclone_to_array() and then reconstructed using deepclone_from_array(), the resulting object no longer has its lazy initializer and its lazy properties remain uninitialized.
This can produce an object in an invalid state and later cause errors such as:
Typed property Foo::$value must not be accessed before initialization
Minimal reproducer
<?php
final class Foo
{
public function __construct(
public string $value,
) {
}
}
$reflection = new ReflectionClass(Foo::class);
$foo = $reflection->newLazyGhost(
static function (Foo $foo): void {
$foo->__construct('test');
},
);
$clone = deepclone_from_array(
deepclone_to_array($foo),
);
var_dump($clone->value);
Expected behavior
The cloned object should contain the fully cloned state:
string(4) "test"
I would expect deepclone_to_array() to initialize an existing uninitialized lazy object before serializing its state, similarly to operations such as native clone.
Actual behavior
The object reconstructed by deepclone_from_array() has no lazy initializer anymore, while its typed properties are still uninitialized.
Accessing the property therefore fails with:
Typed property Foo::$value must not be accessed before initialization
Workaround
Initializing the lazy object explicitly before calling deepclone_to_array() avoids the problem:
$reflection = new ReflectionObject($foo);
if ($reflection->isUninitializedLazyObject($foo)) {
$reflection->initializeLazyObject($foo);
}
$clone = deepclone_from_array(
deepclone_to_array($foo),
);
It would be useful if deepclone_to_array() handled already-existing native lazy ghost objects automatically, so callers do not need to detect and initialize them beforehand.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the deepclone_to_array() and deepclone_from_array() entry points and reproduce the issue using ReflectionClass::newLazyGhost() as shown. Verify that a round trip initializes the lazy ghost and that accessing Foo::$value produces string(4) "test" rather than an uninitialized-property error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, php
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100