Skip to content

Fix deepclone_from_array() issues reported in symfony/polyfill#717 - #64

Merged
nicolas-grekas merged 1 commit into
mainfrom
fuzz-717
Oct 14, 2026
Merged

nicolas-grekas merged 1 commit into
mainfrom
fuzz-717

Conversation

@nicolas-grekas

@nicolas-grekas nicolas-grekas commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Reported in symfony/polyfill#717, which gets the polyfill side in symfony/polyfill#718.

  • The wakeup flags of "objectMeta" were read as 32-bit integers, so 4294967295 read as -1 and -4294967296 as no flag. Only their sign matters now.
  • When deepclone_from_array() returns lazy ghosts, it checks the markers of their properties and states right away, like for other objects. Unknown object or ref ids, values of the wrong type and malformed closures were reported on first access before. What depends on the code, eg a function or an enum case that doesn't exist, still fails on first access.
  • A negative closure index of a const-expr closure is reported before its class is looked up, like its other malformed parts.

The most common marker, an object id, is checked inline: deepclone_from_array() of 1000 objects holding closures runs 1.5% fewer instructions.

nicolas-grekas added a commit to symfony/polyfill that referenced this pull request Oct 14, 2026
…colas-grekas)

This PR was merged into the 1.x branch.

Discussion
----------

[DeepClone] Report malformed payloads like the extension

| Q             | A
| ------------- | ---
| Branch?       | 1.x
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | Fix #717
| License       | MIT

The extension gets its side in symfony/php-ext-deepclone#64.

- An object that only `__unserialize()` can create, eg a `HashContext`, can be referenced before its state is replayed. A missing or malformed state is now reported instead of "unknown object id".
- A non-array state throws the `TypeError` of `__unserialize()`, without mentioning DeepClone.php.
- Binding a reference to a dynamic property doesn't report the deprecation to error handlers anymore. `@` silenced it, but Symfony's ErrorHandler still logged it.
- Messages cut scopes, property names and `"objectMeta"` indexes at their first NUL byte. The closure index of a const-expr closure is checked before its site, like in the extension.
- No more "Undefined array key" warnings for unknown ids in the scope of an internal class.

I didn't check the scope of each object of a property (item 1 of the issue). That costs 3% on `deepclone_from_array()`, for payloads that `deepclone_to_array()` never produces. I left the order of the checks (item 5) and the extra warning of `unserialize()` (item 8) as is too. Both sides reject these payloads.

Commits
-------

e273755 [DeepClone] Report malformed payloads like the extension
@nicolas-grekas
nicolas-grekas merged commit 6007ad6 into main Oct 14, 2026
25 checks passed
@nicolas-grekas
nicolas-grekas deleted the fuzz-717 branch October 14, 2026 09:03
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