diff options
author | setser <[email protected]> | 2022-05-09 00:13:37 +0300 |
---|---|---|
committer | setser <[email protected]> | 2022-05-09 00:13:37 +0300 |
commit | e87e3fc8d0e04eb7ba3eee221bb91613b527ad85 (patch) | |
tree | 5279c128bdbdf902b9a08d9fae8e55b91910a553 /contrib/libs/libxml/xinclude.c | |
parent | f4f3e4024a1f32bd0bc3fa20239025a1b179e42d (diff) |
Update libxml to 2.9.13
ref:f572491d236694e847142c36f0f5546c649e05d7
Diffstat (limited to 'contrib/libs/libxml/xinclude.c')
-rw-r--r-- | contrib/libs/libxml/xinclude.c | 235 |
1 files changed, 127 insertions, 108 deletions
diff --git a/contrib/libs/libxml/xinclude.c b/contrib/libs/libxml/xinclude.c index ba850fa538d..2a0614d737a 100644 --- a/contrib/libs/libxml/xinclude.c +++ b/contrib/libs/libxml/xinclude.c @@ -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++; } @@ -1004,15 +1014,15 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, if (list == NULL) { list = tmp; listParent = cur->parent; + last = tmp; } else { if (level == lastLevel) - xmlAddNextSibling(last, tmp); + last = xmlAddNextSibling(last, tmp); else { - xmlAddChild(last, tmp); + last = xmlAddChild(last, tmp); lastLevel = level; } } - last = tmp; if (index2 > 1) { end = xmlXIncludeGetNthChild(cur, index2 - 1); @@ -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 */ @@ -1093,12 +1103,11 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, } if (tmp != NULL) { if (level == lastLevel) - xmlAddNextSibling(last, tmp); + last = xmlAddNextSibling(last, tmp); else { - xmlAddChild(last, tmp); + last = xmlAddChild(last, tmp); lastLevel = level; } - last = tmp; } } /* @@ -1176,8 +1185,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, if (last == NULL) { list = last = tmp; } else { - xmlAddNextSibling(last, tmp); - last = tmp; + last = xmlAddNextSibling(last, tmp); } cur = cur->next; continue; @@ -1459,7 +1467,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 +1559,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 +1572,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 +1604,7 @@ loaded: XML_XINCLUDE_XPTR_RESULT, "XPointer is not a range: #%s\n", fragment); + xmlXPathFreeObject(xptr); xmlXPathFreeContext(xptrctxt); xmlFree(URL); xmlFree(fragment); @@ -1615,6 +1612,7 @@ loaded: case XPATH_NODESET: if ((xptr->nodesetval == NULL) || (xptr->nodesetval->nodeNr <= 0)) { + xmlXPathFreeObject(xptr); xmlXPathFreeContext(xptrctxt); xmlFree(URL); xmlFree(fragment); @@ -1678,14 +1676,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 +1848,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 +1938,7 @@ xinclude_multibyte_fallback: xmlBufShrink(buf->buffer, len); } xmlFreeParserCtxt(pctxt); - xmlXIncludeAddTxt(ctxt, node, URL); + xmlXIncludeAddTxt(ctxt, node->content, URL); xmlFreeInputStream(inputStream); loaded: @@ -1988,19 +1981,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 +2153,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 +2200,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 +2222,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 +2240,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 +2362,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 +2370,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); @@ -2389,40 +2391,58 @@ 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 +2465,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 +2519,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 +2603,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 +2631,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 +2643,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); |