1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-02-18 05:57:23 +03:00

xinclude: Make xmlXIncludeCopyNode non-recursive

Avoid call stack overflows.

Also switch to xmlStaticCopyNode which avoids duplicate namespace
definitions.
This commit is contained in:
Nick Wellnhofer 2022-10-22 19:08:43 +02:00
parent bc32c3862c
commit 2fc8d12327
3 changed files with 83 additions and 66 deletions

View File

@ -8,4 +8,10 @@
*/
extern int __xmlRegisterCallbacks;
xmlNodePtr
xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
int extended);
xmlNodePtr
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
#endif /* XML_TREE_H_PRIVATE__ */

7
tree.c
View File

@ -4085,9 +4085,6 @@ xmlCopyNamespaceList(xmlNsPtr cur) {
return(ret);
}
static xmlNodePtr
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
static xmlAttrPtr
xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
xmlAttrPtr ret;
@ -4251,7 +4248,7 @@ xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
* namespace info, but don't recurse on children.
*/
static xmlNodePtr
xmlNodePtr
xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
int extended) {
xmlNodePtr ret;
@ -4450,7 +4447,7 @@ out:
return(ret);
}
static xmlNodePtr
xmlNodePtr
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
xmlNodePtr ret = NULL;
xmlNodePtr p = NULL,q;

View File

@ -29,6 +29,7 @@
#include "private/buf.h"
#include "private/error.h"
#include "private/tree.h"
#define XINCLUDE_MAX_DEPTH 40
@ -824,83 +825,96 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
* *
************************************************************************/
static xmlNodePtr
xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem,
xmlNodePtr parent);
/**
* xmlXIncludeCopyNode:
* @ctxt: the XInclude context
* @elem: the element
*
* Make a copy of the node while preserving the XInclude semantic
* of the Infoset copy.
* Make a copy of the node while expanding nested XIncludes.
*
* Returns a node list, not a single node.
*/
static xmlNodePtr
xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem) {
xmlNodePtr result = NULL;
xmlNodePtr insertParent = NULL;
xmlNodePtr insertLast = NULL;
xmlNodePtr cur = elem;
if ((ctxt == NULL) || (elem == NULL))
return(NULL);
if ((elem->type == XML_DOCUMENT_NODE) || (elem->type == XML_DTD_NODE))
return(NULL);
if ((elem->type == XML_ELEMENT_NODE) &&
(elem->ns != NULL) &&
(xmlStrEqual(elem->name, XINCLUDE_NODE)) &&
((xmlStrEqual(elem->ns->href, XINCLUDE_NS)) ||
(xmlStrEqual(elem->ns->href, XINCLUDE_OLD_NS)))) {
xmlXIncludeRefPtr ref = xmlXIncludeExpandNode(ctxt, elem);
while (1) {
xmlNodePtr copy = NULL;
int recurse = 0;
/*
* TODO: Insert XML_XINCLUDE_START and XML_XINCLUDE_END nodes
*/
if ((ref != NULL) && (ref->inc != NULL))
result = xmlDocCopyNodeList(ctxt->doc, ref->inc);
} else {
result = xmlDocCopyNode(elem, ctxt->doc, 2);
if (result == NULL)
return(NULL);
if ((elem->type != XML_ENTITY_REF_NODE) && (elem->children != NULL))
result->children = xmlXIncludeCopyNodeList(ctxt, elem->children,
result);
if ((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_DTD_NODE)) {
;
} else if ((cur->type == XML_ELEMENT_NODE) &&
(cur->ns != NULL) &&
(xmlStrEqual(cur->name, XINCLUDE_NODE)) &&
((xmlStrEqual(cur->ns->href, XINCLUDE_NS)) ||
(xmlStrEqual(cur->ns->href, XINCLUDE_OLD_NS)))) {
xmlXIncludeRefPtr ref = xmlXIncludeExpandNode(ctxt, cur);
if (ref == NULL)
goto error;
/*
* TODO: Insert XML_XINCLUDE_START and XML_XINCLUDE_END nodes
*/
if (ref->inc != NULL) {
copy = xmlStaticCopyNodeList(ref->inc, ctxt->doc,
insertParent);
if (copy == NULL)
goto error;
}
} else {
copy = xmlStaticCopyNode(cur, ctxt->doc, insertParent, 2);
if (copy == NULL)
goto error;
recurse = (cur->type != XML_ENTITY_REF_NODE) &&
(cur->children != NULL);
}
if (copy != NULL) {
if (result == NULL)
result = copy;
if (insertLast != NULL) {
insertLast->next = copy;
copy->prev = insertLast;
} else if (insertParent != NULL) {
insertParent->children = copy;
}
insertLast = copy;
while (insertLast->next != NULL) {
insertLast = insertLast->next;
}
}
if (recurse) {
cur = cur->children;
insertParent = insertLast;
insertLast = NULL;
continue;
}
while ((cur != elem) && (cur->next == NULL)) {
cur = cur->parent;
insertParent->last = insertLast;
insertLast = insertParent;
insertParent = insertParent->parent;
}
if (cur == elem)
break;
cur = cur->next;
}
return(result);
}
/**
* xmlXIncludeCopyNodeList:
* @ctxt: the XInclude context
* @elem: the element list
*
* Make a copy of the node list while preserving the XInclude semantic
* of the Infoset copy
*/
static xmlNodePtr
xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem,
xmlNodePtr parent) {
xmlNodePtr cur, res, result = NULL, last = NULL;
if ((ctxt == NULL) || (elem == NULL))
return(NULL);
cur = elem;
while (cur != NULL) {
res = xmlXIncludeCopyNode(ctxt, cur);
while (res != NULL) {
if (result == NULL) {
result = last = res;
} else {
last->next = res;
res->prev = last;
last = res;
}
res->parent = parent;
res = res->next;
}
cur = cur->next;
}
return(result);
error:
xmlFreeNodeList(result);
return(NULL);
}
#ifdef LIBXML_XPTR_LOCS_ENABLED