Skip to content

Fix UAF when setAttributeNS() frees a wrapped attribute child - #23348

Open
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/dom-modern-setattributens-uaf
Open

Fix UAF when setAttributeNS() frees a wrapped attribute child#23348
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/dom-modern-setattributens-uaf

Conversation

@iliaal

@iliaal iliaal commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Dom\Element::setAttributeNS() replaces an existing attribute's value by calling xmlSetNsProp() directly, and libxml2 frees the attribute's child list there. Nothing unlinks the children that still carry a PHP wrapper first, so a live Dom\Text goes on pointing at freed memory: it reports the new attribute text and claims to still be attached. dom_set_attribute_ns_legacy() has always unlinked them, and the modern setAttribute() replaces the value through dom_remove_all_children(), so only the modern namespace-aware setter is missing the step.

No DTD and no entity reference are needed. A single-text-child attribute is enough, which is why the test builds one rather than reusing the GH-23331 shape.

Independent of #23337, which repairs node_list_unlink() itself. Neither fix needs the other, but an attribute holding TEXT/ENTITY_REF/TEXT needs both: with the two applied that case is valgrind-clean, and with either one alone valgrind still reports an invalid read through the surviving wrapper.

dom_set_attribute_ns_modern() handed the element straight to
xmlSetNsProp(), which frees the existing attribute's child list, so a
live Dom\Text wrapper for one of those children was left pointing at
freed memory. Unlink the wrapped children first, as
dom_set_attribute_ns_legacy() already does.
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.

2 participants