@@ -200,12 +200,36 @@ static void php_libxml_node_free(xmlNodePtr node)
200200 * dtd is attached to the document. This works around the issue by inspecting the parent directly. */
201201 case XML_ENTITY_DECL : {
202202 xmlEntityPtr entity = (xmlEntityPtr ) node ;
203- php_libxml_unlink_entity_decl (entity );
204- if (entity -> orig != NULL ) {
205- xmlFree ((char * ) entity -> orig );
206- entity -> orig = NULL ;
203+ if (entity -> etype != XML_INTERNAL_PREDEFINED_ENTITY ) {
204+ php_libxml_unlink_entity_decl (entity );
205+ #if LIBXML_VERSION >= 21200
206+ xmlFreeEntity (entity );
207+ #else
208+ if (entity -> children != NULL && entity -> owner && entity == (xmlEntityPtr ) entity -> children -> parent ) {
209+ xmlFreeNodeList (entity -> children );
210+ }
211+ xmlDictPtr dict = entity -> doc != NULL ? entity -> doc -> dict : NULL ;
212+ if (dict == NULL || !xmlDictOwns (dict , entity -> name )) {
213+ xmlFree ((xmlChar * ) entity -> name );
214+ }
215+ if (dict == NULL || !xmlDictOwns (dict , entity -> ExternalID )) {
216+ xmlFree ((xmlChar * ) entity -> ExternalID );
217+ }
218+ if (dict == NULL || !xmlDictOwns (dict , entity -> SystemID )) {
219+ xmlFree ((xmlChar * ) entity -> SystemID );
220+ }
221+ if (dict == NULL || !xmlDictOwns (dict , entity -> URI )) {
222+ xmlFree ((xmlChar * ) entity -> URI );
223+ }
224+ if (dict == NULL || !xmlDictOwns (dict , entity -> content )) {
225+ xmlFree (entity -> content );
226+ }
227+ if (dict == NULL || !xmlDictOwns (dict , entity -> orig )) {
228+ xmlFree (entity -> orig );
229+ }
230+ xmlFree (entity );
231+ #endif
207232 }
208- xmlFreeNode (node );
209233 break ;
210234 }
211235 case XML_NOTATION_NODE : {
@@ -1376,6 +1400,15 @@ PHP_LIBXML_API void php_libxml_node_free_resource(xmlNodePtr node)
13761400 case XML_DOCUMENT_NODE :
13771401 case XML_HTML_DOCUMENT_NODE :
13781402 break ;
1403+ case XML_ENTITY_REF_NODE :
1404+ /* Entity reference nodes are special: their children point to entity declarations,
1405+ * but they don't own the declarations and therefore shouldn't free the children.
1406+ * Moreover, there can be more than one reference node for a single entity declarations. */
1407+ php_libxml_unregister_node (node );
1408+ if (node -> parent == NULL ) {
1409+ php_libxml_node_free (node );
1410+ }
1411+ break ;
13791412 default :
13801413 if (node -> parent == NULL || node -> type == XML_NAMESPACE_DECL ) {
13811414 php_libxml_node_free_list ((xmlNodePtr ) node -> children );
0 commit comments