@@ -740,11 +740,43 @@ zend_result dom_node_text_content_write(dom_object *obj, zval *newval)
740740
741741/* }}} */ 
742742
743- static  xmlNodePtr  dom_insert_fragment (xmlNodePtr  nodep , xmlNodePtr  prevsib , xmlNodePtr  nextsib , xmlNodePtr  fragment , dom_object  * intern ) /* {{{ */ 
743+ /* Returns true if the node was changed, false otherwise. */ 
744+ static  bool  dom_set_document_ref_obj_single (xmlNodePtr  node , xmlDocPtr  doc , php_libxml_ref_obj  * document )
744745{
745- 	xmlNodePtr  newchild , node ;
746+ 	dom_object  * childobj  =  php_dom_object_get_data (node );
747+ 	if  (childobj  &&  !childobj -> document ) {
748+ 		childobj -> document  =  document ;
749+ 		document -> refcount ++ ;
750+ 		return  true;
751+ 	}
752+ 	return  false;
753+ }
754+ 
755+ static  void  dom_set_document_pointers (xmlNodePtr  node , xmlDocPtr  doc , php_libxml_ref_obj  * document )
756+ {
757+ 	/* Applies the document to the entire subtree. */ 
758+ 	xmlSetTreeDoc (node , doc );
759+ 
760+ 	if  (!dom_set_document_ref_obj_single (node , doc , document )) {
761+ 		return ;
762+ 	}
763+ 
764+ 	xmlNodePtr  base  =  node ;
765+ 	node  =  node -> children ;
766+ 	while  (node  !=  NULL ) {
767+ 		ZEND_ASSERT (node  !=  base );
768+ 
769+ 		if  (!dom_set_document_ref_obj_single (node , doc , document )) {
770+ 			break ;
771+ 		}
746772
747- 	newchild  =  fragment -> children ;
773+ 		node  =  php_dom_next_in_tree_order (node , base );
774+ 	}
775+ }
776+ 
777+ static  xmlNodePtr  dom_insert_fragment (xmlNodePtr  nodep , xmlNodePtr  prevsib , xmlNodePtr  nextsib , xmlNodePtr  fragment , dom_object  * intern ) /* {{{ */ 
778+ {
779+ 	xmlNodePtr  newchild  =  fragment -> children ;
748780
749781	if  (newchild ) {
750782		if  (prevsib  ==  NULL ) {
@@ -760,17 +792,10 @@ static xmlNodePtr dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, xmlN
760792			nextsib -> prev  =  fragment -> last ;
761793		}
762794
763- 		node  =  newchild ;
795+ 		/* Assign parent node pointer */ 
796+ 		xmlNodePtr  node  =  newchild ;
764797		while  (node  !=  NULL ) {
765798			node -> parent  =  nodep ;
766- 			if  (node -> doc  !=  nodep -> doc ) {
767- 				xmlSetTreeDoc (node , nodep -> doc );
768- 				dom_object  * childobj  =  node -> _private ;
769- 				if  (childobj  !=  NULL ) {
770- 					childobj -> document  =  intern -> document ;
771- 					php_libxml_increment_doc_ref ((php_libxml_node_object  * )childobj , NULL );
772- 				}
773- 			}
774799			if  (node  ==  fragment -> last ) {
775800				break ;
776801			}
@@ -835,8 +860,7 @@ static void dom_node_insert_before_legacy(zval *return_value, zval *ref, dom_obj
835860	}
836861
837862	if  (child -> doc  ==  NULL  &&  parentp -> doc  !=  NULL ) {
838- 		childobj -> document  =  intern -> document ;
839- 		php_libxml_increment_doc_ref ((php_libxml_node_object  * )childobj , NULL );
863+ 		dom_set_document_pointers (child , parentp -> doc , intern -> document );
840864	}
841865
842866	php_libxml_invalidate_node_list_cache (intern -> document );
@@ -856,9 +880,6 @@ static void dom_node_insert_before_legacy(zval *return_value, zval *ref, dom_obj
856880
857881		if  (child -> type  ==  XML_TEXT_NODE  &&  (refp -> type  ==  XML_TEXT_NODE  || 
858882			(refp -> prev  !=  NULL  &&  refp -> prev -> type  ==  XML_TEXT_NODE ))) {
859- 			if  (child -> doc  ==  NULL ) {
860- 				xmlSetTreeDoc (child , parentp -> doc );
861- 			}
862883			new_child  =  child ;
863884			new_child -> parent  =  refp -> parent ;
864885			new_child -> next  =  refp ;
@@ -910,9 +931,6 @@ static void dom_node_insert_before_legacy(zval *return_value, zval *ref, dom_obj
910931		}
911932		if  (child -> type  ==  XML_TEXT_NODE  &&  parentp -> last  !=  NULL  &&  parentp -> last -> type  ==  XML_TEXT_NODE ) {
912933			child -> parent  =  parentp ;
913- 			if  (child -> doc  ==  NULL ) {
914- 				xmlSetTreeDoc (child , parentp -> doc );
915- 			}
916934			new_child  =  child ;
917935			if  (parentp -> children  ==  NULL ) {
918936				parentp -> children  =  child ;
@@ -1155,6 +1173,10 @@ static void dom_node_replace_child(INTERNAL_FUNCTION_PARAMETERS, bool modern)
11551173		}
11561174	}
11571175
1176+ 	if  (newchild -> doc  ==  NULL  &&  nodep -> doc  !=  NULL ) {
1177+ 		dom_set_document_pointers (newchild , nodep -> doc , intern -> document );
1178+ 	}
1179+ 
11581180	if  (newchild -> type  ==  XML_DOCUMENT_FRAG_NODE ) {
11591181		xmlNodePtr  prevsib , nextsib ;
11601182		prevsib  =  oldchild -> prev ;
@@ -1171,11 +1193,6 @@ static void dom_node_replace_child(INTERNAL_FUNCTION_PARAMETERS, bool modern)
11711193		xmlDtdPtr  intSubset  =  xmlGetIntSubset (nodep -> doc );
11721194		bool  replacedoctype  =  (intSubset  ==  (xmlDtd  * ) oldchild );
11731195
1174- 		if  (newchild -> doc  ==  NULL  &&  nodep -> doc  !=  NULL ) {
1175- 			xmlSetTreeDoc (newchild , nodep -> doc );
1176- 			newchildobj -> document  =  intern -> document ;
1177- 			php_libxml_increment_doc_ref ((php_libxml_node_object  * )newchildobj , NULL );
1178- 		}
11791196		xmlReplaceNode (oldchild , newchild );
11801197		if  (!modern ) {
11811198			dom_reconcile_ns (nodep -> doc , newchild );
@@ -1265,8 +1282,7 @@ static void dom_node_append_child_legacy(zval *return_value, dom_object *intern,
12651282	}
12661283
12671284	if  (child -> doc  ==  NULL  &&  nodep -> doc  !=  NULL ) {
1268- 		childobj -> document  =  intern -> document ;
1269- 		php_libxml_increment_doc_ref ((php_libxml_node_object  * )childobj , NULL );
1285+ 		dom_set_document_pointers (child , nodep -> doc , intern -> document );
12701286	}
12711287
12721288	if  (child -> parent  !=  NULL ){
@@ -1275,9 +1291,6 @@ static void dom_node_append_child_legacy(zval *return_value, dom_object *intern,
12751291
12761292	if  (child -> type  ==  XML_TEXT_NODE  &&  nodep -> last  !=  NULL  &&  nodep -> last -> type  ==  XML_TEXT_NODE ) {
12771293		child -> parent  =  nodep ;
1278- 		if  (child -> doc  ==  NULL ) {
1279- 			xmlSetTreeDoc (child , nodep -> doc );
1280- 		}
12811294		new_child  =  child ;
12821295		if  (nodep -> children  ==  NULL ) {
12831296			nodep -> children  =  child ;
0 commit comments