Skip to content

XPath callback UAF #22078

Closed
afflerbach wants to merge 1 commit into
php:PHP-8.5from
afflerbach:xpath-callback-uaf
Closed

XPath callback UAF #22078
afflerbach wants to merge 1 commit into
php:PHP-8.5from
afflerbach:xpath-callback-uaf

Conversation

@afflerbach
Copy link
Copy Markdown
Contributor

@afflerbach afflerbach commented May 18, 2026

Try to fix #22077

@afflerbach afflerbach requested a review from devnexen as a code owner May 18, 2026 06:49
@afflerbach afflerbach changed the base branch from master to PHP-8.5 May 18, 2026 06:49
@afflerbach afflerbach changed the title XPath callback UAF #22077 XPath callback UAF May 18, 2026
@devnexen
Copy link
Copy Markdown
Member

devnexen commented May 18, 2026

you have been faster than me, nice but I m afraid your fix is incomplete I can see leaks locally with your changes. Ah well your commit said it all.

@devnexen
Copy link
Copy Markdown
Member

devnexen commented May 18, 2026

let me think about it unless you come up with the solution in the meantime. I ve been maintaining these extensions for few weeks now, I can tell by experience most of proper fixes are not "one-liners" ;)

Comment thread ext/dom/xpath_callbacks.c Outdated
@devnexen
Copy link
Copy Markdown
Member

Can you revert your change and try the following ?

Somewhere in ext/dom/xpath.c

+/* in xpath.c, near top */
+static dom_object *dom_xpath_intern_for_doc(dom_xpath_object *xpath_obj, xmlDocPtr doc)
+{
+       if (xpath_obj->dom.document && xpath_obj->dom.document->ptr == doc) {
+               return &xpath_obj->dom;
+       }
+       HashTable *node_list = xpath_obj->xpath_callbacks.node_list;
+       if (node_list) {
+               zval *entry;
+               ZEND_HASH_PACKED_FOREACH_VAL(node_list, entry) {
+                       dom_object *obj = Z_DOMOBJ_P(entry);
+                       if (obj->document && obj->document->ptr == doc) {
+                               return obj;
+                       }
+               } ZEND_HASH_FOREACH_END();
+       }
+       return &xpath_obj->dom;
+}
+

then

HashTable *dom_xpath_get_gc(zend_object *object, zval **table, int *n)
 {
        dom_xpath_object *intern = php_xpath_obj_from_obj(object);
@@ -352,7 +371,8 @@ static void php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS, int type, bool modern)
 
                                                node = php_dom_create_fake_namespace_decl(nsparent, original, &child, parent_intern);
                                        } else {
-                                               php_dom_create_object(node, &child, &intern->dom);
+                                               dom_object *parent = dom_xpath_intern_for_doc(intern, node->doc);
+                                               php_dom_create_object(node, &child, parent);
                                        }
                                        add_next_index_zval(&retval, &child);

@afflerbach
Copy link
Copy Markdown
Contributor Author

This looks good (as far as I can tell ;), no UAF, no leak

afflerbach added a commit to afflerbach/php-src that referenced this pull request May 18, 2026
@devnexen
Copy link
Copy Markdown
Member

Can you do the following ?

  • squash in 1 commit adding the ext/dom: prefix.
  • adding me with the Co-Authored-by tag.
    thanks.

@afflerbach afflerbach force-pushed the xpath-callback-uaf branch 2 times, most recently from f527fab to 0a254f7 Compare May 18, 2026 08:23
Copy link
Copy Markdown
Member

@devnexen devnexen left a comment

Choose a reason for hiding this comment

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

lgtm

Comment thread ext/dom/tests/bug22077.phpt Outdated
@@ -0,0 +1,25 @@
--TEST--
test for issue #22077
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.

just few nits about the test.

here should be

GH-22077 (UAF in custom XPath function)

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.

name of the name file should be gh22077.phpt (since we moved on from the old bugs.php.net to github).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

Comment thread ext/dom/tests/bug22077.phpt Outdated
@@ -0,0 +1,25 @@
--TEST--
test for issue #22077
--DESCRIPTION--
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.

The --DESCRIPTION-- block is heavier than php-src precedent. Most phpt tests drop it entirely (only ~10 in the repo use it, and the typical body is a single short
line, e.g. run this with valgrind in Zend/tests/bug60825.phpt). I'd fold the summary into --TEST-- itself

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. I had written this before I created the ticket.

@devnexen
Copy link
Copy Markdown
Member

just few nits to address regarding the unit test then I ll commit shortly :)

Co-authored-by: David CARLIER <devnexen@gmail.com>
@afflerbach afflerbach force-pushed the xpath-callback-uaf branch from 0a254f7 to 0d27cb7 Compare May 18, 2026 09:11
@devnexen devnexen closed this in 33a49bb May 18, 2026
@devnexen
Copy link
Copy Markdown
Member

Thanks !

@afflerbach
Copy link
Copy Markdown
Contributor Author

Thank you for the great support!

@devnexen devnexen linked an issue May 18, 2026 that may be closed by this pull request
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.

UAF in custom XPath function

2 participants