@@ -1076,10 +1076,62 @@ static void php_dom_transfer_document_ref(xmlNodePtr node, php_libxml_ref_obj *n
1076
1076
}
1077
1077
}
1078
1078
1079
+ /* Workaround for bug that was fixed in https://github.com/GNOME/libxml2/commit/4bc3ebf3eaba352fbbce2ef70ad00a3c7752478a
1080
+ * and https://github.com/GNOME/libxml2/commit/bc7ab5a2e61e4b36accf6803c5b0e245c11154b1 */
1081
+ #if LIBXML_VERSION < 21300
1082
+ static xmlChar * libxml_copy_dicted_string (xmlDictPtr src_dict , xmlDictPtr dst_dict , xmlChar * str )
1083
+ {
1084
+ if (str == NULL ) {
1085
+ return NULL ;
1086
+ }
1087
+ if (xmlDictOwns (src_dict , str ) == 1 ) {
1088
+ if (dst_dict == NULL ) {
1089
+ return xmlStrdup (str );
1090
+ }
1091
+ return BAD_CAST xmlDictLookup (dst_dict , str , -1 );
1092
+ }
1093
+ return str ;
1094
+ }
1095
+
1096
+ static void libxml_fixup_name_and_content (xmlDocPtr src_doc , xmlDocPtr dst_doc , xmlNodePtr node )
1097
+ {
1098
+ if (node -> type == XML_ENTITY_REF_NODE ) {
1099
+ node -> children = NULL ; /* Break link with original document. */
1100
+ }
1101
+ if (src_doc != NULL && src_doc -> dict != NULL ) {
1102
+ ZEND_ASSERT (dst_doc != src_doc );
1103
+ node -> name = libxml_copy_dicted_string (src_doc -> dict , dst_doc -> dict , BAD_CAST node -> name );
1104
+ node -> content = libxml_copy_dicted_string (src_doc -> dict , NULL , node -> content );
1105
+ }
1106
+ }
1107
+
1108
+ static void libxml_fixup_name_and_content_outer (xmlDocPtr src_doc , xmlDocPtr dst_doc , xmlNodePtr node )
1109
+ {
1110
+ libxml_fixup_name_and_content (src_doc , dst_doc , node );
1111
+
1112
+ if (node -> type == XML_ELEMENT_NODE ) {
1113
+ for (xmlAttrPtr attr = node -> properties ; attr != NULL ; attr = attr -> next ) {
1114
+ libxml_fixup_name_and_content (src_doc , dst_doc , (xmlNodePtr ) attr );
1115
+ for (xmlNodePtr attr_child = attr -> children ; attr_child != NULL ; attr_child = attr_child -> next ) {
1116
+ libxml_fixup_name_and_content (src_doc , dst_doc , attr_child );
1117
+ }
1118
+ }
1119
+ }
1120
+
1121
+ if (node -> type == XML_ELEMENT_NODE || node -> type == XML_ATTRIBUTE_NODE ) {
1122
+ for (xmlNodePtr child = node -> children ; child != NULL ; child = child -> next ) {
1123
+ libxml_fixup_name_and_content_outer (src_doc , dst_doc , child );
1124
+ }
1125
+ }
1126
+ }
1127
+ #endif
1128
+
1079
1129
bool php_dom_adopt_node (xmlNodePtr nodep , dom_object * dom_object_new_document , xmlDocPtr new_document )
1080
1130
{
1081
- php_libxml_invalidate_node_list_cache_from_doc (nodep -> doc );
1082
- if (nodep -> doc != new_document ) {
1131
+ xmlDocPtr old_doc = nodep -> doc ;
1132
+
1133
+ php_libxml_invalidate_node_list_cache_from_doc (old_doc );
1134
+ if (old_doc != new_document ) {
1083
1135
php_libxml_invalidate_node_list_cache (dom_object_new_document -> document );
1084
1136
1085
1137
/* Note for ATTRIBUTE_NODE: specified is always true in ext/dom,
@@ -1089,6 +1141,11 @@ bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, x
1089
1141
return false;
1090
1142
}
1091
1143
1144
+ #if LIBXML_VERSION < 21300
1145
+ /* Must be first before transferring the ref to ensure the old document dictionary stays alive. */
1146
+ libxml_fixup_name_and_content_outer (old_doc , new_document , nodep );
1147
+ #endif
1148
+
1092
1149
php_dom_transfer_document_ref (nodep , dom_object_new_document -> document );
1093
1150
} else {
1094
1151
xmlUnlinkNode (nodep );
0 commit comments