Skip to content

ext/dom: fix use-after-free with XPath callback returning foreign-doc… - #24570

Closed
devnexen wants to merge 3 commits into
php:PHP-8.4from
devnexen:gh24545
Closed

devnexen wants to merge 3 commits into
php:PHP-8.4from
devnexen:gh24545

Conversation

@devnexen

Copy link
Copy Markdown
Member

…ument node.

Fix GH-22554

A PHP XPath callback that returns a node belonging to a document created inside the callback (e.g. $d->documentElement of a throwaway DOMDocument) parks that node in the DOMXPath node_list to keep it alive. When a sibling callback consumes a node navigated into that foreign document, the proxy object was created with the DOMXPath's own dom as parent, so it took a reference on the wrong document and none on the foreign one. On teardown the foreign document could be freed while the proxy still referenced it.

Route the proxy factory through dom_xpath_intern_for_doc() so the created object shares the ref_obj of the node's actual document, mirroring the query-result path.

close GH-22562

(cherry picked from commit f36660d)

@ndossche

Copy link
Copy Markdown
Member

It breaks on 8.4 too though. Was targeting 8.5 only deliberate?

@devnexen

devnexen commented Oct 22, 2026 •

Copy link
Copy Markdown
Member Author

oh ... 8.4 is more involved I would need to backport more. updating...

afflerbach and others added 3 commits October 22, 2026 20:11
Co-authored-by: David CARLIER <devnexen@gmail.com>

close phpGH-22078

(cherry picked from commit 33a49bb)
…ument node.

Fix phpGH-22554

A PHP XPath callback that returns a node belonging to a document created
inside the callback (e.g. $d->documentElement of a throwaway DOMDocument)
parks that node in the DOMXPath node_list to keep it alive. When a sibling
callback consumes a node navigated into that foreign document, the proxy
object was created with the DOMXPath's own dom as parent, so it took a
reference on the wrong document and none on the foreign one. On teardown the
foreign document could be freed while the proxy still referenced it.

Route the proxy factory through dom_xpath_intern_for_doc() so the created
object shares the ref_obj of the node's actual document, mirroring the
query-result path.

close phpGH-22562

(cherry picked from commit f36660d)
dom_xpath_intern_for_doc walked xpath_callbacks.node_list with
Z_DOMOBJ_P on every entry. That list also stores arrays (nodeset-mode
callback arguments). Same-document results take the early return; a
later php:function that returns a node from another document walks
the leftover array first. Skip non-objects and recurse into arrays
so the matching intern is found instead of type-confusing the array.

Closes phpGH-23253

(cherry picked from commit fcdc4fb)
@devnexen
devnexen changed the base branch from PHP-8.5 to PHP-8.4 October 22, 2026 19:14
@devnexen
devnexen marked this pull request as ready for review October 22, 2026 19:42

@iliaal iliaal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

G2G, nice fix.

@devnexen devnexen closed this in a44a529 Oct 23, 2026
@ndossche

Copy link
Copy Markdown
Member

Doesn't the namespace axis have the same problem? (i.e. namespace::*) ?

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.

Heap corruption in DOMXPath PHP callbacks during XSLT transformation (malloc(): unaligned tcache chunk detected)

4 participants