| Index: third_party/libxml/src/xpath.c
|
| diff --git a/third_party/libxml/src/xpath.c b/third_party/libxml/src/xpath.c
|
| index 132930bbbe16f63911b1895c096529fcabe1b086..620e81441a0ade3f33c5d32b543e8549573e86b1 100644
|
| --- a/third_party/libxml/src/xpath.c
|
| +++ b/third_party/libxml/src/xpath.c
|
| @@ -945,7 +945,7 @@ struct _xmlXPathCompExpr {
|
| xmlXPathStepOp *steps; /* ops for computation of this expression */
|
| int last; /* index of last step in expression */
|
| xmlChar *expr; /* the expression being computed */
|
| - xmlDictPtr dict; /* the dictionnary to use if any */
|
| + xmlDictPtr dict; /* the dictionary to use if any */
|
| #ifdef DEBUG_EVAL_COUNTS
|
| int nb;
|
| xmlChar *string;
|
| @@ -1132,7 +1132,6 @@ xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
|
| comp->steps[comp->nbStep].value5 = value5;
|
| }
|
| comp->steps[comp->nbStep].cache = NULL;
|
| - comp->steps[comp->nbStep].cacheURI = NULL;
|
| return(comp->nbStep++);
|
| }
|
|
|
| @@ -3707,7 +3706,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
|
|
|
| /* @@ with_ns to check whether namespace nodes should be looked at @@ */
|
| /*
|
| - * prevent duplcates
|
| + * prevent duplicates
|
| */
|
| for (i = 0;i < cur->nodeNr;i++)
|
| if (cur->nodeTab[i] == val) return(0);
|
| @@ -8391,7 +8390,7 @@ xmlNodePtr
|
| xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
|
| if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
|
| if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
|
| - if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
|
| + if (cur == NULL) {
|
| if (ctxt->context->tmpNsList != NULL)
|
| xmlFree(ctxt->context->tmpNsList);
|
| ctxt->context->tmpNsList =
|
| @@ -9997,7 +9996,7 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
|
| (c == '[') || (c == ']') || (c == '@') || /* accelerators */
|
| (c == '*') || /* accelerators */
|
| (!IS_LETTER(c) && (c != '_') &&
|
| - ((qualified) && (c != ':')))) {
|
| + ((!qualified) || (c != ':')))) {
|
| return(NULL);
|
| }
|
|
|
| @@ -12380,11 +12379,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
|
| STRANGE
|
| goto error;
|
| case NODE_TEST_TYPE:
|
| - /*
|
| - * TODO: Don't we need to use
|
| - * xmlXPathNodeSetAddNs() for namespace nodes here?
|
| - * Surprisingly, some c14n tests fail, if we do this.
|
| - */
|
| if (type == NODE_TYPE_NODE) {
|
| switch (cur->type) {
|
| case XML_DOCUMENT_NODE:
|
| @@ -12398,9 +12392,17 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
|
| case XML_COMMENT_NODE:
|
| case XML_CDATA_SECTION_NODE:
|
| case XML_TEXT_NODE:
|
| - case XML_NAMESPACE_DECL:
|
| XP_TEST_HIT
|
| break;
|
| + case XML_NAMESPACE_DECL: {
|
| + if (axis == AXIS_NAMESPACE) {
|
| + XP_TEST_HIT_NS
|
| + } else {
|
| + hasNsNodes = 1;
|
| + XP_TEST_HIT
|
| + }
|
| + break;
|
| + }
|
| default:
|
| break;
|
| }
|
| @@ -12692,6 +12694,14 @@ error:
|
| * Reset the context node.
|
| */
|
| xpctxt->node = oldContextNode;
|
| + /*
|
| + * When traversing the namespace axis in "toBool" mode, it's
|
| + * possible that tmpNsList wasn't freed.
|
| + */
|
| + if (xpctxt->tmpNsList != NULL) {
|
| + xmlFree(xpctxt->tmpNsList);
|
| + xpctxt->tmpNsList = NULL;
|
| + }
|
|
|
| #ifdef DEBUG_STEP
|
| xmlGenericError(xmlGenericErrorContext,
|
| @@ -14733,12 +14743,8 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
|
| #endif /* XPATH_STREAMING */
|
|
|
| static void
|
| -xmlXPathOptimizeExpressionInternal(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
|
| +xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
|
| {
|
| - /* Already optimized? */
|
| - if (op->cacheURI != NULL)
|
| - return;
|
| -
|
| /*
|
| * Try to rewrite "descendant-or-self::node()/foo" to an optimized
|
| * internal representation.
|
| @@ -14789,28 +14795,15 @@ xmlXPathOptimizeExpressionInternal(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr o
|
| }
|
| }
|
|
|
| - /* Mark the node. */
|
| - op->cacheURI = (void*)(~0);
|
| + /* OP_VALUE has invalid ch1. */
|
| + if (op->op == XPATH_OP_VALUE)
|
| + return;
|
|
|
| /* Recurse */
|
| if (op->ch1 != -1)
|
| - xmlXPathOptimizeExpressionInternal(comp, &comp->steps[op->ch1]);
|
| + xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);
|
| if (op->ch2 != -1)
|
| - xmlXPathOptimizeExpressionInternal(comp, &comp->steps[op->ch2]);
|
| -}
|
| -
|
| -static void
|
| -xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, int root)
|
| -{
|
| - int i;
|
| - /* The expression tree/graph traversal is linear, visiting
|
| - * each node at most once. Mark each xmlXPathStepOp node
|
| - * upon visiting, taking care of clearing out the marks
|
| - * afterwards.
|
| - */
|
| - xmlXPathOptimizeExpressionInternal(comp, &comp->steps[root]);
|
| - for (i = 0; i <= root; ++i)
|
| - comp->steps[i].cacheURI = NULL;
|
| + xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]);
|
| }
|
|
|
| /**
|
| @@ -14869,7 +14862,7 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
|
| comp->nb = 0;
|
| #endif
|
| if ((comp->nbStep > 1) && (comp->last >= 0)) {
|
| - xmlXPathOptimizeExpression(comp, comp->last);
|
| + xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]);
|
| }
|
| }
|
| return(comp);
|
| @@ -15051,7 +15044,8 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
|
| (ctxt->comp->nbStep > 1) &&
|
| (ctxt->comp->last >= 0))
|
| {
|
| - xmlXPathOptimizeExpression(ctxt->comp, ctxt->comp->last);
|
| + xmlXPathOptimizeExpression(ctxt->comp,
|
| + &ctxt->comp->steps[ctxt->comp->last]);
|
| }
|
| }
|
| CHECK_ERROR;
|
|
|