@@ -1566,6 +1566,58 @@ static void php_dom_remove_xinclude_nodes(xmlNodePtr cur) /* {{{ */
15661566}
15671567/* }}} */
15681568
1569+ /* Backported from master branch xml_common.h */
1570+ static zend_always_inline xmlNodePtr php_dom_next_in_tree_order (const xmlNode * nodep , const xmlNode * basep )
1571+ {
1572+ if (nodep -> type == XML_ELEMENT_NODE && nodep -> children ) {
1573+ return nodep -> children ;
1574+ }
1575+
1576+ if (nodep -> next ) {
1577+ return nodep -> next ;
1578+ } else {
1579+ /* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */
1580+ do {
1581+ nodep = nodep -> parent ;
1582+ if (nodep == basep ) {
1583+ return NULL ;
1584+ }
1585+ } while (nodep -> next == NULL );
1586+ return nodep -> next ;
1587+ }
1588+ }
1589+
1590+ static void dom_xinclude_strip_references (xmlNodePtr basep )
1591+ {
1592+ php_libxml_node_free_resource (basep );
1593+
1594+ xmlNodePtr current = basep -> children ;
1595+
1596+ while (current ) {
1597+ php_libxml_node_free_resource (current );
1598+ current = php_dom_next_in_tree_order (current , basep );
1599+ }
1600+ }
1601+
1602+ /* See GH-14702.
1603+ * We have to remove userland references to xinclude fallback nodes because libxml2 will make clones of these
1604+ * and remove the original nodes. If the originals are removed while there are still userland references
1605+ * this will cause memory corruption. */
1606+ static void dom_xinclude_strip_fallback_references (const xmlNode * basep )
1607+ {
1608+ xmlNodePtr current = basep -> children ;
1609+
1610+ while (current ) {
1611+ if (current -> type == XML_ELEMENT_NODE && current -> ns != NULL && current -> _private != NULL
1612+ && xmlStrEqual (current -> name , XINCLUDE_FALLBACK )
1613+ && (xmlStrEqual (current -> ns -> href , XINCLUDE_NS ) || xmlStrEqual (current -> ns -> href , XINCLUDE_OLD_NS ))) {
1614+ dom_xinclude_strip_references (current );
1615+ }
1616+
1617+ current = php_dom_next_in_tree_order (current , basep );
1618+ }
1619+ }
1620+
15691621/* {{{ Substitutues xincludes in a DomDocument */
15701622PHP_METHOD (DOMDocument , xinclude )
15711623{
@@ -1588,6 +1640,8 @@ PHP_METHOD(DOMDocument, xinclude)
15881640
15891641 DOM_GET_OBJ (docp , id , xmlDocPtr , intern );
15901642
1643+ dom_xinclude_strip_fallback_references ((const xmlNode * ) docp );
1644+
15911645 PHP_LIBXML_SANITIZE_GLOBALS (xinclude );
15921646 err = xmlXIncludeProcessFlags (docp , (int )flags );
15931647 PHP_LIBXML_RESTORE_GLOBALS (xinclude );
0 commit comments