Skip to content

Keep the object alive across jsonSerialize() in json_encode()#126

Closed
iliaal wants to merge 1 commit into
PHP-8.5from
fix/gh21024-json-jsonserialize-uaf
Closed

Keep the object alive across jsonSerialize() in json_encode()#126
iliaal wants to merge 1 commit into
PHP-8.5from
fix/gh21024-json-jsonserialize-uaf

Conversation

@iliaal

@iliaal iliaal commented Jun 26, 2026

Copy link
Copy Markdown
Owner

json_encode() can use-after-free a JsonSerializable object when its jsonSerialize() triggers a user error handler that frees the object, for example by nulling a reference that aliases the encoded array slot. php_json_encode_serializable_object() holds a raw pointer to the object across the call and then reads its recursion guard and compares identity against the return value.

Fix: hold a reference on the object across the call. The array path already guards against this with a ZVAL_COPY ("Avoid modifications (and potential freeing) of the array... when a jsonSerialize() method is invoked"); the JsonSerializable object path did not.

php_json_encode_serializable_object() holds a raw pointer to the object
across the jsonSerialize() call, then reads its recursion guard and
compares the returned value's identity against it. A user error handler
triggered from jsonSerialize() can drop the last reference to the object,
for example by nulling a reference that aliases the encoded array slot,
freeing it before those reads and causing a use-after-free.

Hold a reference on the object across the call. The array path already
guards against this with a ZVAL_COPY; the JsonSerializable object path
did not. Same use-after-free class as phpGH-21024 in var_dump().
@iliaal iliaal force-pushed the fix/gh21024-json-jsonserialize-uaf branch from d538277 to d37595a Compare June 26, 2026 12:33
@iliaal iliaal changed the base branch from master to PHP-8.5 June 26, 2026 12:33
@iliaal

iliaal commented Jun 26, 2026

Copy link
Copy Markdown
Owner Author

Submitted upstream as php#22469.

@iliaal iliaal closed this Jun 26, 2026
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