Fix UAF when setAttributeNS() frees a wrapped attribute child - #23348
Open
iliaal wants to merge 1 commit into
Open
Fix UAF when setAttributeNS() frees a wrapped attribute child#23348iliaal wants to merge 1 commit into
iliaal wants to merge 1 commit into
Conversation
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.
devnexen
approved these changes
Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.