[LIBXML2] Update to version 2.9.12. CORE-17766

This commit is contained in:
Thomas Faber 2021-09-12 13:24:24 -04:00
parent 271556e6f8
commit 40ee59d609
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
60 changed files with 3385 additions and 2832 deletions

View file

@ -59,7 +59,7 @@ struct _xmlXIncludeRef {
xmlNodePtr inc; /* the included copy */
int xml; /* xml or txt */
int count; /* how many refs use that specific doc */
xmlXPathObjectPtr xptr; /* the xpointer if needed */
int fallback; /* fallback was loaded */
int emptyFb; /* flag to show fallback empty */
};
@ -72,7 +72,7 @@ struct _xmlXIncludeCtxt {
int txtNr; /* number of unparsed documents */
int txtMax; /* size of unparsed documents tab */
xmlNodePtr *txtTab; /* array of unparsed text nodes */
xmlChar * *txtTab; /* array of unparsed text strings */
xmlURL *txturlTab; /* array of unparsed text URLs */
xmlChar * url; /* the current URL processed */
@ -86,10 +86,13 @@ struct _xmlXIncludeCtxt {
xmlChar * base; /* the current xml:base */
void *_private; /* application data */
unsigned long incTotal; /* total number of processed inclusions */
};
static int
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
int skipRoot);
/************************************************************************
@ -207,8 +210,6 @@ xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
xmlFree(ref->URI);
if (ref->fragment != NULL)
xmlFree(ref->fragment);
if (ref->xptr != NULL)
xmlXPathFreeObject(ref->xptr);
xmlFree(ref);
}
@ -392,18 +393,22 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
if (ctxt->incTab[i] != NULL)
xmlXIncludeFreeRef(ctxt->incTab[i]);
}
if (ctxt->incTab != NULL)
xmlFree(ctxt->incTab);
if (ctxt->txtTab != NULL) {
for (i = 0;i < ctxt->txtNr;i++) {
if (ctxt->txtTab[i] != NULL)
xmlFree(ctxt->txtTab[i]);
}
xmlFree(ctxt->txtTab);
}
if (ctxt->txturlTab != NULL) {
for (i = 0;i < ctxt->txtNr;i++) {
if (ctxt->txturlTab[i] != NULL)
xmlFree(ctxt->txturlTab[i]);
}
}
if (ctxt->incTab != NULL)
xmlFree(ctxt->incTab);
if (ctxt->txtTab != NULL)
xmlFree(ctxt->txtTab);
if (ctxt->txturlTab != NULL)
xmlFree(ctxt->txturlTab);
}
if (ctxt->base != NULL) {
xmlFree(ctxt->base);
}
@ -626,8 +631,8 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
"detected a local recursion with no xpointer in %s\n",
URL);
if (fragment != NULL)
xmlFree(fragment);
xmlFree(URL);
xmlFree(fragment);
return(-1);
}
@ -639,12 +644,15 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
if (xmlStrEqual(URL, ctxt->urlTab[i])) {
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
"detected a recursion in %s\n", URL);
xmlFree(URL);
xmlFree(fragment);
return(-1);
}
}
}
ref = xmlXIncludeNewRef(ctxt, URL, cur);
xmlFree(URL);
if (ref == NULL) {
return(-1);
}
@ -652,7 +660,6 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
ref->doc = NULL;
ref->xml = xml;
ref->count = 1;
xmlFree(URL);
return(0);
}
@ -729,7 +736,9 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
* (bug 132597)
*/
newctxt->parseFlags = ctxt->parseFlags;
xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
newctxt->incTotal = ctxt->incTotal;
xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc), 0);
ctxt->incTotal = newctxt->incTotal;
for (i = 0;i < ctxt->incNr;i++) {
newctxt->incTab[i]->count--;
newctxt->incTab[i] = NULL;
@ -759,13 +768,14 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
* Add a new text node to the list
*/
static void
xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
const xmlURL url) {
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
#endif
if (ctxt->txtMax == 0) {
ctxt->txtMax = 4;
ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
ctxt->txtTab = (xmlChar **) xmlMalloc(ctxt->txtMax *
sizeof(ctxt->txtTab[0]));
if (ctxt->txtTab == NULL) {
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
@ -780,7 +790,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
}
if (ctxt->txtNr >= ctxt->txtMax) {
ctxt->txtMax *= 2;
ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
ctxt->txtTab = (xmlChar **) xmlRealloc(ctxt->txtTab,
ctxt->txtMax * sizeof(ctxt->txtTab[0]));
if (ctxt->txtTab == NULL) {
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
@ -793,7 +803,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
return;
}
}
ctxt->txtTab[ctxt->txtNr] = txt;
ctxt->txtTab[ctxt->txtNr] = xmlStrdup(txt);
ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
ctxt->txtNr++;
}
@ -1071,7 +1081,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_NODE:
/* Do not copy DTD informations */
/* Do not copy DTD information */
break;
case XML_ENTITY_DECL:
/* handle crossing entities -> stack needed */
@ -1459,7 +1469,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
*/
if ((URL[0] == 0) || (URL[0] == '#') ||
((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
doc = NULL;
doc = ctxt->doc;
goto loaded;
}
@ -1551,15 +1561,8 @@ loaded:
/*
* Add the top children list as the replacement copy.
*/
if (doc == NULL)
{
/* Hopefully a DTD declaration won't be copied from
* the same document */
ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
} else {
ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
doc, doc->children);
}
ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
doc, doc->children);
}
#ifdef LIBXML_XPTR_ENABLED
else {
@ -1571,12 +1574,7 @@ loaded:
xmlXPathContextPtr xptrctxt;
xmlNodeSetPtr set;
if (doc == NULL) {
xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
NULL);
} else {
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
}
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
if (xptrctxt == NULL) {
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
XML_XINCLUDE_XPTR_FAILED,
@ -1608,6 +1606,7 @@ loaded:
XML_XINCLUDE_XPTR_RESULT,
"XPointer is not a range: #%s\n",
fragment);
xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
@ -1615,6 +1614,7 @@ loaded:
case XPATH_NODESET:
if ((xptr->nodesetval == NULL) ||
(xptr->nodesetval->nodeNr <= 0)) {
xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
@ -1678,14 +1678,9 @@ loaded:
}
}
}
if (doc == NULL) {
ctxt->incTab[nr]->xptr = xptr;
ctxt->incTab[nr]->inc = NULL;
} else {
ctxt->incTab[nr]->inc =
xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
xmlXPathFreeObject(xptr);
}
ctxt->incTab[nr]->inc =
xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(fragment);
}
@ -1855,7 +1850,7 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
*/
for (i = 0; i < ctxt->txtNr; i++) {
if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
node = xmlCopyNode(ctxt->txtTab[i], 1);
node = xmlNewText(ctxt->txtTab[i]);
goto loaded;
}
}
@ -1945,7 +1940,7 @@ xinclude_multibyte_fallback:
xmlBufShrink(buf->buffer, len);
}
xmlFreeParserCtxt(pctxt);
xmlXIncludeAddTxt(ctxt, node, URL);
xmlXIncludeAddTxt(ctxt, node->content, URL);
xmlFreeInputStream(inputStream);
loaded:
@ -1988,19 +1983,23 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
newctxt->_private = ctxt->_private;
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
newctxt->incTotal = ctxt->incTotal;
if (xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback, 1) < 0)
ret = -1;
ctxt->incTotal = newctxt->incTotal;
if (ctxt->nbErrors > oldNbErrors)
ret = -1;
else if (ret > 0)
ret = 0; /* xmlXIncludeDoProcess can return +ve number */
xmlXIncludeFreeContext(newctxt);
ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
fallback->children);
if (ctxt->incTab[nr]->inc == NULL)
ctxt->incTab[nr]->emptyFb = 1;
} else {
ctxt->incTab[nr]->inc = NULL;
ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
}
ctxt->incTab[nr]->fallback = 1;
return(ret);
}
@ -2156,8 +2155,7 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
(xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
ret = xmlXIncludeLoadFallback(ctxt, children, nr);
if (ret == 0)
break;
break;
}
children = children->next;
}
@ -2204,19 +2202,9 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
return(-1);
/*
* If we stored an XPointer a late computation may be needed
*/
if ((ctxt->incTab[nr]->inc == NULL) &&
(ctxt->incTab[nr]->xptr != NULL)) {
ctxt->incTab[nr]->inc =
xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
ctxt->incTab[nr]->xptr);
xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
ctxt->incTab[nr]->xptr = NULL;
}
list = ctxt->incTab[nr]->inc;
ctxt->incTab[nr]->inc = NULL;
ctxt->incTab[nr]->emptyFb = 0;
/*
* Check against the risk of generating a multi-rooted document
@ -2236,6 +2224,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
XML_XINCLUDE_MULTIPLE_ROOT,
"XInclude error: would result in multiple root nodes\n",
NULL);
xmlFreeNodeList(list);
return(-1);
}
}
@ -2253,16 +2242,27 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlUnlinkNode(cur);
xmlFreeNode(cur);
} else {
xmlNodePtr child, next;
/*
* Change the current node as an XInclude start one, and add an
* XInclude end one
*/
if (ctxt->incTab[nr]->fallback)
xmlUnsetProp(cur, BAD_CAST "href");
cur->type = XML_XINCLUDE_START;
/* Remove fallback children */
for (child = cur->children; child != NULL; child = next) {
next = child->next;
xmlUnlinkNode(child);
xmlFreeNode(child);
}
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
if (end == NULL) {
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
XML_XINCLUDE_BUILD_FAILED,
"failed to build node\n", NULL);
xmlFreeNodeList(list);
return(-1);
}
end->type = XML_XINCLUDE_END;
@ -2364,6 +2364,7 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* @ctxt: the XInclude processing context
* @doc: an XML document
* @tree: the top of the tree to process
* @skipRoot: don't process the root node of the tree
*
* Implement the XInclude substitution on the XML document @doc
*
@ -2371,13 +2372,16 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* or the number of substitutions done.
*/
static int
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
int skipRoot) {
xmlNodePtr cur;
int ret = 0;
int i, start;
if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
return(-1);
if ((skipRoot) && (tree->children == NULL))
return(-1);
if (ctxt == NULL)
return(-1);
@ -2388,41 +2392,59 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
}
start = ctxt->incNr;
/*
* TODO: The phases must run separately for recursive inclusions.
*
* - Phase 1 should start with top-level XInclude nodes, load documents,
* execute XPointer expressions, then process only the result nodes
* (not whole document, see bug #324081) and only for phase 1
* recursively. We will need a backreference from xmlNodes to
* xmlIncludeRefs to detect references that were already visited.
* This can also be used for proper cycle detection, see bug #344240.
*
* - Phase 2 should visit all top-level XInclude nodes and expand
* possible subreferences in the replacement recursively.
*
* - Phase 3 should finally replace the top-level XInclude nodes.
* It could also be run together with phase 2.
*/
/*
* First phase: lookup the elements in the document
*/
cur = tree;
if (xmlXIncludeTestNode(ctxt, cur) == 1)
xmlXIncludePreProcessNode(ctxt, cur);
while ((cur != NULL) && (cur != tree->parent)) {
if (skipRoot)
cur = tree->children;
else
cur = tree;
do {
/* TODO: need to work on entities -> stack */
if ((cur->children != NULL) &&
(cur->children->type != XML_ENTITY_DECL) &&
(cur->children->type != XML_XINCLUDE_START) &&
(cur->children->type != XML_XINCLUDE_END)) {
cur = cur->children;
if (xmlXIncludeTestNode(ctxt, cur))
xmlXIncludePreProcessNode(ctxt, cur);
} else if (cur->next != NULL) {
cur = cur->next;
if (xmlXIncludeTestNode(ctxt, cur))
xmlXIncludePreProcessNode(ctxt, cur);
} else {
if (cur == tree)
break;
do {
cur = cur->parent;
if ((cur == NULL) || (cur == tree->parent))
break; /* do */
if (cur->next != NULL) {
cur = cur->next;
if (xmlXIncludeTestNode(ctxt, cur))
xmlXIncludePreProcessNode(ctxt, cur);
break; /* do */
}
} while (cur != NULL);
}
}
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/*
* Avoid superlinear expansion by limiting the total number
* of replacements.
*/
if (ctxt->incTotal >= 20)
return(-1);
#endif
ctxt->incTotal++;
xmlXIncludePreProcessNode(ctxt, cur);
} else if ((cur->children != NULL) &&
((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_ELEMENT_NODE))) {
cur = cur->children;
continue;
}
do {
if (cur == tree)
break;
if (cur->next != NULL) {
cur = cur->next;
break;
}
cur = cur->parent;
} while (cur != NULL);
} while ((cur != NULL) && (cur != tree));
/*
* Second Phase : collect the infosets fragments
@ -2445,8 +2467,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
*/
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
if ((ctxt->incTab[i]->inc != NULL) ||
(ctxt->incTab[i]->xptr != NULL) ||
(ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
(ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
xmlXIncludeIncludeNode(ctxt, i);
}
@ -2500,7 +2521,7 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
ctxt->_private = data;
ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
xmlXIncludeSetFlags(ctxt, flags);
ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@ -2584,7 +2605,7 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
return(-1);
ctxt->base = xmlNodeGetBase(tree->doc, tree);
xmlXIncludeSetFlags(ctxt, flags);
ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@ -2612,7 +2633,7 @@ xmlXIncludeProcessTree(xmlNodePtr tree) {
* @node: a node in an XML document
*
* Implement the XInclude substitution for the given subtree reusing
* the informations and data coming from the given context.
* the information and data coming from the given context.
*
* Returns 0 if no substitution were done, -1 if some processing failed
* or the number of substitutions done.
@ -2624,7 +2645,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
(node->doc == NULL) || (ctxt == NULL))
return(-1);
ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
ret = xmlXIncludeDoProcess(ctxt, node->doc, node, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
return(ret);