Repository navigation
Conversation
…ecursion spl_array_set_array() only rejected an ArrayObject using itself as storage. Two objects using each other as storage were accepted, and the next access recursed in spl_array_get_hash_table_ptr() until the stack overflowed. Follow the chain of objects used as storage and throw an InvalidArgumentException if it leads back to the object.
Member
|
I'm not sure this is even worth fixing considering that using objects as backing storage has been deprecated and will be removed in the future. |
Contributor
Author
|
Thanks for taking a look. Agreed that this goes away once object backing storage is removed. I targeted PHP-8.4 because there it isn't deprecated yet and the result is a segfault rather than an error. If you'd rather not change 8.4 for this, I'm happy to close the PR and the issue. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
spl_array_set_array()accepts anotherArrayObject/ArrayIteratoras storage (SPL_ARRAY_USE_OTHER) and only special-cases an object that uses itself (SPL_ARRAY_IS_SELF). Two objects that use each other as storage are accepted, and the next access to the storage recurses inspl_array_get_hash_table_ptr()until the stack overflows:The same cycle can be built through
__construct(),__unserialize()/unserialize(), withArrayIterator, and over longer chains.Fix
Before accepting another
ArrayObject/ArrayIteratoras storage, follow its chain ofSPL_ARRAY_USE_OTHERobjects and throw anInvalidArgumentException("Cannot use ArrayObject as storage of ArrayObject, as it would create a cycle") if the chain leads back to the object. This is done before anything is changed, so the object keeps its previous storage. Every path that sets the storage goes throughspl_array_set_array(), so all of the above are covered. The walk needs no bound: each object has at most one storage object, and with this check the chains stay acyclic. Using an object as its own storage and sharing storage without a cycle still work.Test
ext/spl/tests/gh24615.phptbuilds two-object and three-object cycles (throughexchangeArray(),__construct()and__unserialize(), with anArrayIteratorin the chain). It checks that each attempt throws and leaves the objects usable, and that self storage and acyclic sharing still work.Termsig=11, stack overflow inspl_array_get_hash_table_ptr()).ext/spl/tests(debug build): 768 passed, 9 skipped, 0 failed.The branch also merges cleanly into PHP-8.5 and master. On master, object storage for
ArrayObjectis deprecated, so the test will need the deprecation notices in its expected output (orE_DEPRECATEDturned off) after merging up.Fixes GH-24615
This issue was found by an LLM-Enhanced Static Analysis Engine and verified manually; the patch was manually reviewed.
🤖 Generated with Claude Code