Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GH-17736: Assertion failure zend_reference_destroy() #17739

Open
wants to merge 2 commits into
base: PHP-8.3
Choose a base branch
from

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Feb 8, 2025

The cache slot for FETCH_OBJ_W in function test is primed for C::$a. The next call uses a simplexml instance and reuses the same cache slot. simplexml's get_property_ptr handler does not use the cache slot, so the old values remain in the cache slot. When zend_handle_fetch_obj_flags is called this is not guarded by a check for the class entry. So we end up using the prop_info from the property C::$a instead of the simplexml property.

This patch adds a check for the class entry. I placed the check as late as possible to avoid as much overhead as possible. An alternative solution is to write NULLs to the cache slot in the get_property_ptr handlers of extensions that don't use the cache slot, but that is not general: not only simplexml would need changes, maybe even third party extensions would need changes as well.

The cache slot for FETCH_OBJ_W in function `test` is primed with the
class for C. The next call uses a simplexml instance and reuses the same
cache slot. simplexml's get_property_ptr handler does not use the cache
slot, so the old values remain in the cache slot. When
`zend_handle_fetch_obj_flags` is called this is not guarded by a check
for the class entry. So we end up using the prop_info from the property
C::$a instead of the simplexml property.

This patch adds a check for the class entry. I placed the check as late
as possible to avoid as much overhead as possible.
An alternative solution is to write NULLs to the cache slot in the
get_property_ptr handlers of extensions that don't use the cache slot,
but that is not general: not only simplexml would need changes, maybe
even third party extensions would need changes as well.
@nielsdos nielsdos marked this pull request as ready for review February 8, 2025 12:39
@nielsdos nielsdos requested a review from dstogov as a code owner February 8, 2025 12:39
@iluuu1994
Copy link
Member

Does this need handling in the JIT? Specifically, zend_jit_fetch_obj_w_slow()? The code-path looks very similar.

@nielsdos
Copy link
Member Author

nielsdos commented Feb 8, 2025

Probably, hang on.

@nielsdos
Copy link
Member Author

nielsdos commented Feb 8, 2025

Pushed the equivalent change for JIT, I could reproduce it with function JIT.

if (prop_info) {
if (prop_info && EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is something wrong.
This check should be done in zend_get_property_offset().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be sxe_property_get_adr should invalidate the cache.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dstogov Niels referenced this solution here:

An alternative solution is to write NULLs to the cache slot in the get_property_ptr handlers of extensions that don't use the cache slot, but that is not general: not only simplexml would need changes, maybe even third party extensions would need changes as well.

I think it's not obvious that handlers that don't use the cache need to clear it. It's probably the better solution, but we should document it clearly (maybe in the comments of the handler for best visibility, and then in UPGRADING.INTERNALS).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dstogov Niels referenced this solution here:

An alternative solution is to write NULLs to the cache slot in the get_property_ptr handlers of extensions that don't use the cache slot, but that is not general: not only simplexml would need changes, maybe even third party extensions would need changes as well.

I think it's not obvious that handlers that don't use the cache need to clear it. It's probably the better solution, but we should document it clearly (maybe in the comments of the handler for best visibility, and then in UPGRADING.INTERNALS).

I'm not sure about the best way to fix this, but the current solution that keeps run-time cache in inconsistent state looks like a hack. Especially for zend_fetch_property_address() we may clear it right here (after the first failed check).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Assertion failure zend_reference_destroy()
3 participants