@@ -1625,6 +1625,58 @@ static void php_dom_remove_xinclude_nodes(xmlNodePtr cur) /* {{{ */
16251625}
16261626/* }}} */
16271627
1628+ /* Backported from master branch xml_common.h */
1629+ static zend_always_inline xmlNodePtr php_dom_next_in_tree_order (const xmlNode * nodep , const xmlNode * basep )
1630+ {
1631+ if (nodep -> type == XML_ELEMENT_NODE && nodep -> children ) {
1632+ return nodep -> children ;
1633+ }
1634+
1635+ if (nodep -> next ) {
1636+ return nodep -> next ;
1637+ } else {
1638+ /* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */
1639+ do {
1640+ nodep = nodep -> parent ;
1641+ if (nodep == basep ) {
1642+ return NULL ;
1643+ }
1644+ } while (nodep -> next == NULL );
1645+ return nodep -> next ;
1646+ }
1647+ }
1648+
1649+ static void dom_xinclude_strip_references (xmlNodePtr basep )
1650+ {
1651+ php_libxml_node_free_resource (basep );
1652+
1653+ xmlNodePtr current = basep -> children ;
1654+
1655+ while (current ) {
1656+ php_libxml_node_free_resource (current );
1657+ current = php_dom_next_in_tree_order (current , basep );
1658+ }
1659+ }
1660+
1661+ /* See GH-14702.
1662+ * We have to remove userland references to xinclude fallback nodes because libxml2 will make clones of these
1663+ * and remove the original nodes. If the originals are removed while there are still userland references
1664+ * this will cause memory corruption. */
1665+ static void dom_xinclude_strip_fallback_references (const xmlNode * basep )
1666+ {
1667+ xmlNodePtr current = basep -> children ;
1668+
1669+ while (current ) {
1670+ if (current -> type == XML_ELEMENT_NODE && current -> ns != NULL && current -> _private != NULL
1671+ && xmlStrEqual (current -> name , XINCLUDE_FALLBACK )
1672+ && (xmlStrEqual (current -> ns -> href , XINCLUDE_NS ) || xmlStrEqual (current -> ns -> href , XINCLUDE_OLD_NS ))) {
1673+ dom_xinclude_strip_references (current );
1674+ }
1675+
1676+ current = php_dom_next_in_tree_order (current , basep );
1677+ }
1678+ }
1679+
16281680/* {{{ Substitutues xincludes in a DomDocument */
16291681PHP_METHOD (DOMDocument , xinclude )
16301682{
@@ -1647,6 +1699,8 @@ PHP_METHOD(DOMDocument, xinclude)
16471699
16481700 DOM_GET_OBJ (docp , id , xmlDocPtr , intern );
16491701
1702+ dom_xinclude_strip_fallback_references ((const xmlNode * ) docp );
1703+
16501704 PHP_LIBXML_SANITIZE_GLOBALS (xinclude );
16511705 err = xmlXIncludeProcessFlags (docp , (int )flags );
16521706 PHP_LIBXML_RESTORE_GLOBALS (xinclude );
0 commit comments