| Index: third_party/libxslt/libxslt/transform.c
|
| diff --git a/third_party/libxslt/libxslt/transform.c b/third_party/libxslt/libxslt/transform.c
|
| index a4ca41df380ee2686b852b14713bd82958728c64..35701deabb6eb3546461223687521b5f1b928be7 100644
|
| --- a/third_party/libxslt/libxslt/transform.c
|
| +++ b/third_party/libxslt/libxslt/transform.c
|
| @@ -20,6 +20,7 @@
|
| #include "libxslt.h"
|
|
|
| #include <string.h>
|
| +#include <stdio.h>
|
|
|
| #include <libxml/xmlmemory.h>
|
| #include <libxml/parser.h>
|
| @@ -64,6 +65,7 @@ static int xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,
|
| #endif
|
|
|
| int xsltMaxDepth = 3000;
|
| +int xsltMaxVars = 15000;
|
|
|
| /*
|
| * Useful macros
|
| @@ -125,7 +127,7 @@ templPush(xsltTransformContextPtr ctxt, xsltTemplatePtr value)
|
| return (0);
|
| }
|
| }
|
| - if (ctxt->templNr >= ctxt->templMax) {
|
| + else if (ctxt->templNr >= ctxt->templMax) {
|
| ctxt->templMax *= 2;
|
| ctxt->templTab =
|
| (xsltTemplatePtr *) xmlRealloc(ctxt->templTab,
|
| @@ -249,7 +251,7 @@ profPush(xsltTransformContextPtr ctxt, long value)
|
| return (0);
|
| }
|
| }
|
| - if (ctxt->profNr >= ctxt->profMax) {
|
| + else if (ctxt->profNr >= ctxt->profMax) {
|
| ctxt->profMax *= 2;
|
| ctxt->profTab =
|
| (long *) xmlRealloc(ctxt->profTab,
|
| @@ -288,6 +290,54 @@ profPop(xsltTransformContextPtr ctxt)
|
| return (ret);
|
| }
|
|
|
| +static void
|
| +profCallgraphAdd(xsltTemplatePtr templ, xsltTemplatePtr parent)
|
| +{
|
| + int i;
|
| +
|
| + if (templ->templMax == 0) {
|
| + templ->templMax = 4;
|
| + templ->templCalledTab =
|
| + (xsltTemplatePtr *) xmlMalloc(templ->templMax *
|
| + sizeof(templ->templCalledTab[0]));
|
| + templ->templCountTab =
|
| + (int *) xmlMalloc(templ->templMax *
|
| + sizeof(templ->templCountTab[0]));
|
| + if (templ->templCalledTab == NULL || templ->templCountTab == NULL) {
|
| + xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
|
| + return;
|
| + }
|
| + }
|
| + else if (templ->templNr >= templ->templMax) {
|
| + templ->templMax *= 2;
|
| + templ->templCalledTab =
|
| + (xsltTemplatePtr *) xmlRealloc(templ->templCalledTab,
|
| + templ->templMax *
|
| + sizeof(templ->templCalledTab[0]));
|
| + templ->templCountTab =
|
| + (int *) xmlRealloc(templ->templCountTab,
|
| + templ->templMax *
|
| + sizeof(templ->templCountTab[0]));
|
| + if (templ->templCalledTab == NULL || templ->templCountTab == NULL) {
|
| + xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
|
| + return;
|
| + }
|
| + }
|
| +
|
| + for (i = 0; i < templ->templNr; i++) {
|
| + if (templ->templCalledTab[i] == parent) {
|
| + templ->templCountTab[i]++;
|
| + break;
|
| + }
|
| + }
|
| + if (i == templ->templNr) {
|
| + /* not found, add new one */
|
| + templ->templCalledTab[templ->templNr] = parent;
|
| + templ->templCountTab[templ->templNr] = 1;
|
| + templ->templNr++;
|
| + }
|
| +}
|
| +
|
| /************************************************************************
|
| * *
|
| * XInclude default settings *
|
| @@ -456,6 +506,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
|
| cur->templNr = 0;
|
| cur->templMax = 5;
|
| cur->templ = NULL;
|
| + cur->maxTemplateDepth = xsltMaxDepth;
|
|
|
| /*
|
| * initialize the variables stack
|
| @@ -471,6 +522,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
|
| cur->varsMax = 10;
|
| cur->vars = NULL;
|
| cur->varsBase = 0;
|
| + cur->maxTemplateVars = xsltMaxVars;
|
|
|
| /*
|
| * the profiling stack is not initialized by default
|
| @@ -726,7 +778,7 @@ xsltCopyTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,
|
| #endif
|
|
|
| /*
|
| - * Play save and reset the merging mechanism for every new
|
| + * Play safe and reset the merging mechanism for every new
|
| * target node.
|
| */
|
| if ((target == NULL) || (target->children == NULL)) {
|
| @@ -2935,8 +2987,7 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
|
| * Check for infinite recursion: stop if the maximum of nested templates
|
| * is excceeded. Adjust xsltMaxDepth if you need more.
|
| */
|
| - if (((ctxt->templNr >= xsltMaxDepth) ||
|
| - (ctxt->varsNr >= 5 * xsltMaxDepth)))
|
| + if (ctxt->templNr >= ctxt->maxTemplateDepth)
|
| {
|
| xsltTransformError(ctxt, NULL, list,
|
| "xsltApplyXSLTTemplate: A potential infinite template recursion "
|
| @@ -2944,11 +2995,23 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
|
| "You can adjust xsltMaxDepth (--maxdepth) in order to "
|
| "raise the maximum number of nested template calls and "
|
| "variables/params (currently set to %d).\n",
|
| - xsltMaxDepth);
|
| + ctxt->maxTemplateDepth);
|
| xsltDebug(ctxt, contextNode, list, NULL);
|
| return;
|
| }
|
|
|
| + if (ctxt->varsNr >= ctxt->maxTemplateVars)
|
| + {
|
| + xsltTransformError(ctxt, NULL, list,
|
| + "xsltApplyXSLTTemplate: A potential infinite template recursion "
|
| + "was detected.\n"
|
| + "You can adjust maxTemplateVars (--maxvars) in order to "
|
| + "raise the maximum number of variables/params (currently set to %d).\n",
|
| + ctxt->maxTemplateVars);
|
| + xsltDebug(ctxt, contextNode, list, NULL);
|
| + return;
|
| + }
|
| +
|
| oldUserFragmentTop = ctxt->tmpRVT;
|
| ctxt->tmpRVT = NULL;
|
| oldLocalFragmentTop = ctxt->localRVT;
|
| @@ -2964,6 +3027,7 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
|
| templ->nbCalls++;
|
| start = xsltTimestamp();
|
| profPush(ctxt, 0);
|
| + profCallgraphAdd(templ, ctxt->templ);
|
| }
|
| /*
|
| * Push the xsl:template declaration onto the stack.
|
| @@ -3230,6 +3294,7 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| const xmlChar *doctypeSystem;
|
| const xmlChar *version;
|
| const xmlChar *encoding;
|
| + int redirect_write_append = 0;
|
|
|
| if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
|
| return;
|
| @@ -3645,10 +3710,38 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| }
|
|
|
| /*
|
| - * Save the result
|
| + * Calls to redirect:write also take an optional attribute append.
|
| + * Attribute append="true|yes" which will attempt to simply append
|
| + * to an existing file instead of always opening a new file. The
|
| + * default behavior of always overwriting the file still happens
|
| + * if we do not specify append.
|
| + * Note that append use will forbid use of remote URI target.
|
| */
|
| - ret = xsltSaveResultToFilename((const char *) filename,
|
| - res, style, 0);
|
| + prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"append",
|
| + NULL);
|
| + if (prop != NULL) {
|
| + if (xmlStrEqual(prop, (const xmlChar *) "true") ||
|
| + xmlStrEqual(prop, (const xmlChar *) "yes")) {
|
| + style->omitXmlDeclaration = 1;
|
| + redirect_write_append = 1;
|
| + } else
|
| + style->omitXmlDeclaration = 0;
|
| + xmlFree(prop);
|
| + }
|
| +
|
| + if (redirect_write_append) {
|
| + FILE *f;
|
| +
|
| + f = fopen((const char *) filename, "ab");
|
| + if (f == NULL) {
|
| + ret = -1;
|
| + } else {
|
| + ret = xsltSaveResultToFile(f, res, style);
|
| + fclose(f);
|
| + }
|
| + } else {
|
| + ret = xsltSaveResultToFilename((const char *) filename, res, style, 0);
|
| + }
|
| if (ret < 0) {
|
| xsltTransformError(ctxt, NULL, inst,
|
| "xsltDocumentElem: unable to save to %s\n",
|
| @@ -3915,14 +4008,6 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| }
|
| name = xsltSplitQName(ctxt->dict, prop, &prefix);
|
| xmlFree(prop);
|
| - if ((prefix != NULL) &&
|
| - (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
|
| - {
|
| - /*
|
| - * TODO: Should we really disallow an "xml" prefix?
|
| - */
|
| - goto error;
|
| - }
|
| } else {
|
| /*
|
| * The "name" value was static.
|
| @@ -3977,7 +4062,19 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
|
| nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
|
| xmlFree(tmpNsName);
|
| - };
|
| + }
|
| +
|
| + if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
|
| + xsltTransformError(ctxt, NULL, inst,
|
| + "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
|
| + "forbidden.\n");
|
| + goto error;
|
| + }
|
| + if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
|
| + prefix = BAD_CAST "xml";
|
| + } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
|
| + prefix = NULL;
|
| + }
|
| } else {
|
| xmlNsPtr ns;
|
| /*
|
| @@ -3993,13 +4090,13 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| * TODO: Check this in the compilation layer in case it's a
|
| * static value.
|
| */
|
| - if (prefix != NULL) {
|
| - xsltTransformError(ctxt, NULL, inst,
|
| - "xsl:element: The QName '%s:%s' has no "
|
| - "namespace binding in scope in the stylesheet; "
|
| - "this is an error, since the namespace was not "
|
| - "specified by the instruction itself.\n", prefix, name);
|
| - }
|
| + if (prefix != NULL) {
|
| + xsltTransformError(ctxt, NULL, inst,
|
| + "xsl:element: The QName '%s:%s' has no "
|
| + "namespace binding in scope in the stylesheet; "
|
| + "this is an error, since the namespace was not "
|
| + "specified by the instruction itself.\n", prefix, name);
|
| + }
|
| } else
|
| nsName = ns->href;
|
| }
|
| @@ -4007,7 +4104,17 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| * Find/create a matching ns-decl in the result tree.
|
| */
|
| if (nsName != NULL) {
|
| - copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix, copy);
|
| + if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
|
| + /* Don't use a prefix of "xmlns" */
|
| + xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
|
| +
|
| + copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, pref, copy);
|
| +
|
| + xmlFree(pref);
|
| + } else {
|
| + copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
|
| + copy);
|
| + }
|
| } else if ((copy->parent != NULL) &&
|
| (copy->parent->type == XML_ELEMENT_NODE) &&
|
| (copy->parent->ns != NULL))
|
| @@ -4364,7 +4471,6 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| xsltStylePreCompPtr comp = castedComp;
|
| #endif
|
| xmlXPathObjectPtr res = NULL;
|
| - xmlNodePtr copy = NULL;
|
| xmlChar *value = NULL;
|
| xmlDocPtr oldXPContextDoc;
|
| xmlNsPtr *oldXPNamespaces;
|
| @@ -4437,8 +4543,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| goto error;
|
| }
|
| if (value[0] != 0) {
|
| - copy = xsltCopyTextString(ctxt,
|
| - ctxt->insert, value, comp->noescape);
|
| + xsltCopyTextString(ctxt, ctxt->insert, value, comp->noescape);
|
| }
|
| } else {
|
| xsltTransformError(ctxt, NULL, inst,
|
| @@ -4832,7 +4937,10 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| list = xmlXPathNodeSetCreate(NULL);
|
| if (list == NULL)
|
| goto error;
|
| - cur = node->children;
|
| + if (node->type != XML_NAMESPACE_DECL)
|
| + cur = node->children;
|
| + else
|
| + cur = NULL;
|
| while (cur != NULL) {
|
| switch (cur->type) {
|
| case XML_TEXT_NODE:
|
| @@ -4881,6 +4989,8 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
| if (cur->prev != NULL)
|
| cur->prev->next = cur->next;
|
| break;
|
| + case XML_NAMESPACE_DECL:
|
| + break;
|
| default:
|
| #ifdef WITH_XSLT_DEBUG_PROCESS
|
| XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
|
|
|