Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[DeepClone] Drop SPL "\0" special key from deepclone_hydrate()#584

Merged
nicolas-grekas merged 1 commit into1.xsymfony/polyfill:1.xfrom
clean-serializablesymfony/polyfill:clean-serializableCopy head branch name to clipboard
Apr 26, 2026
Merged

[DeepClone] Drop SPL "\0" special key from deepclone_hydrate()#584
nicolas-grekas merged 1 commit into1.xsymfony/polyfill:1.xfrom
clean-serializablesymfony/polyfill:clean-serializableCopy head branch name to clipboard

Conversation

@nicolas-grekas
Copy link
Copy Markdown
Member

Mirrors symfony/php-ext-deepclone#17.

ArrayObject, ArrayIterator and SplObjectStorage all ship __serialize / __unserialize since PHP 7.4. The "\0" special key in deepclone_hydrate() was a port from Symfony's legacy Hydrator API and added bespoke handling that duplicated what these classes natively expose.

Callers now populate these objects the standard way:

$ao = deepclone_hydrate('ArrayObject');
$ao->__unserialize([ArrayObject::ARRAY_AS_PROPS, ['x' => 1, 'y' => 2], []]);

$s = deepclone_hydrate('SplObjectStorage');
$s->__unserialize([[$o1, 'info1', $o2, 'info2'], []]);

Or just round-trip via deepclone_from_array(), which routes through __unserialize natively.

The mangled-key resolution path ("propName", "\0*\0prop", "\0Class\0prop") is unchanged; only the SPL fast-path is removed. Tests updated to use __unserialize().

Symfony's Hydrator::hydrate() / Instantiator::instantiate() keep BC by translating the legacy "\0" shape to __unserialize() themselves.

Mirrors the C extension change (symfony/php-ext-deepclone#17). ArrayObject,
ArrayIterator and SplObjectStorage all ship __serialize / __unserialize
since PHP 7.4 — callers populate them the standard way:

    $ao = deepclone_hydrate('ArrayObject');
    $ao->__unserialize([ArrayObject::ARRAY_AS_PROPS, ['x' => 1], []]);

The mangled-key resolution path is unchanged; only the SPL fast-path is
removed. Symfony's Hydrator/Instantiator retain BC by translating the
legacy "\0" shape to __unserialize() themselves.
@nicolas-grekas nicolas-grekas merged commit 461b3d3 into 1.x Apr 26, 2026
2 of 20 checks passed
@nicolas-grekas nicolas-grekas deleted the clean-serializable branch April 26, 2026 13:07
nicolas-grekas added a commit to symfony/symfony that referenced this pull request Apr 26, 2026
…lize() in Hydrator/Instantiator (nicolas-grekas)

This PR was merged into the 8.1 branch.

Discussion
----------

[VarExporter] Translate legacy SPL "\0" key to __unserialize() in Hydrator/Instantiator

| Q             | A
| ------------- | ---
| Branch?       | 8.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

`deepclone_hydrate()` no longer treats the special `"\0"` key as SPL internal state (see symfony/php-ext-deepclone#17 / symfony/polyfill#584). `ArrayObject`, `ArrayIterator` and `SplObjectStorage` all ship `__serialize` / `__unserialize` since PHP 7.4 — the C extension and polyfill now expect callers to use the standard path.

This PR keeps BC for `Hydrator::hydrate()` and `Instantiator::instantiate()`: when `$mangledVars` contains a `"\0"` key with the legacy shape, it is intercepted and translated to a `__unserialize()` call.

Mapping:
* `SplObjectStorage`: `"\0" => [$obj1, $info1, $obj2, $info2, ...]` → `__unserialize([[$obj1, $info1, ...], []])`
* `ArrayObject`: `"\0" => [$array, $flags?, $iteratorClass?]` → `__unserialize([$flags ?? 0, $array, [], $iteratorClass ?? ArrayIterator::class])`
* `ArrayIterator`: `"\0" => [$array, $flags?]` → `__unserialize([$flags ?? 0, $array, []])`

In `Instantiator::instantiate()`, the `__unserialize()` call happens after instantiation so the constructor is still skipped.

Depends on symfony/polyfill#584 (which depends on symfony/php-ext-deepclone#17).

Commits
-------

54d013b [VarExporter] Translate legacy SPL "\0" key to __unserialize() in Hydrator/Instantiator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.