[libxslt] Fix for pattern predicates calling functions



commit bf6c947bf6b77d28344829cd489b1f19eeb26536
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Jan 3 15:42:26 2017 +0100

    Fix for pattern predicates calling functions
    
    Set correct XSLT instruction when evaluating predicates in patterns.
    This is needed by functions like element-available. Could also lead
    to a NULL pointer dereference.
    
    Thanks to Wang Junjie for the report. Fixes bug #776792:
    
    https://bugzilla.gnome.org/show_bug.cgi?id=776792

 libxslt/functions.c       |    2 +-
 libxslt/pattern.c         |   30 ++++++++++++++++++------------
 libxslt/templates.c       |   12 ++++++++++++
 tests/docs/bug-200.xml    |    1 +
 tests/general/bug-200.out |    2 ++
 tests/general/bug-200.xsl |    5 +++++
 6 files changed, 39 insertions(+), 13 deletions(-)
---
diff --git a/libxslt/functions.c b/libxslt/functions.c
index a5e7021..5e99e92 100644
--- a/libxslt/functions.c
+++ b/libxslt/functions.c
@@ -835,7 +835,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
     }
     obj = valuePop(ctxt);
     tctxt = xsltXPathGetTransformContext(ctxt);
-    if (tctxt == NULL) {
+    if ((tctxt == NULL) || (tctxt->inst == NULL)) {
        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                "element-available() : internal error tctxt == NULL\n");
        xmlXPathFreeObject(obj);
diff --git a/libxslt/pattern.c b/libxslt/pattern.c
index e211a01..8359e4b 100644
--- a/libxslt/pattern.c
+++ b/libxslt/pattern.c
@@ -104,6 +104,7 @@ struct _xsltCompMatch {
     const xmlChar *mode;         /* the mode */
     const xmlChar *modeURI;      /* the mode URI */
     xsltTemplatePtr template;    /* the associated template */
+    xmlNodePtr node;             /* the containing element */
 
     int direct;
     /* TODO fix the statically allocated size steps[] */
@@ -914,7 +915,9 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
                  xmlNodePtr matchNode, const xmlChar *mode,
                  const xmlChar *modeURI) {
     int i;
+    int found = 0;
     xmlNodePtr node = matchNode;
+    xmlNodePtr oldInst;
     xsltStepOpPtr step, sel = NULL;
     xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
 
@@ -948,6 +951,10 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
            return(0);
     }
 
+    /* Some XPath functions rely on inst being set correctly. */
+    oldInst = ctxt->inst;
+    ctxt->inst = comp->node;
+
     i = 0;
 restart:
     for (;i < comp->nbStep;i++) {
@@ -1140,12 +1147,9 @@ restart:
                 * as possible this costly computation.
                 */
                if (comp->direct) {
-                   if (states.states != NULL) {
-                       /* Free the rollback states */
-                       xmlFree(states.states);
-                   }
-                   return(xsltTestCompMatchDirect(ctxt, comp, matchNode,
-                                                  comp->nsList, comp->nsNr));
+                   found = xsltTestCompMatchDirect(ctxt, comp, matchNode,
+                                                   comp->nsList, comp->nsNr);
+                    goto exit;
                }
 
                if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
@@ -1185,18 +1189,19 @@ restart:
        }
     }
 found:
+    found = 1;
+exit:
+    ctxt->inst = oldInst;
     if (states.states != NULL) {
         /* Free the rollback states */
        xmlFree(states.states);
     }
-    return(1);
+    return found;
 rollback:
     /* got an error try to rollback */
-    if (states.states == NULL)
-       return(0);
-    if (states.nbstates <= 0) {
-       xmlFree(states.states);
-       return(0);
+    if (states.states == NULL || states.nbstates <= 0) {
+        found = 0;
+       goto exit;
     }
     states.nbstates--;
     i = states.states[states.nbstates].step;
@@ -1944,6 +1949,7 @@ xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,
            goto error;
        ctxt->cur = &(ctxt->base)[current - start];
        element->pattern = ctxt->base;
+        element->node = node;
        element->nsList = xmlGetNsList(doc, node);
        j = 0;
        if (element->nsList != NULL) {
diff --git a/libxslt/templates.c b/libxslt/templates.c
index 02193f7..ad83dce 100644
--- a/libxslt/templates.c
+++ b/libxslt/templates.c
@@ -63,6 +63,12 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
     xmlNodePtr oldInst;
     int oldProximityPosition, oldContextSize;
 
+    if ((ctxt == NULL) || (ctxt->inst == NULL)) {
+        xsltTransformError(ctxt, NULL, NULL,
+            "xsltEvalXPathPredicate: No context or instruction\n");
+        return(0);
+    }
+
     oldContextSize = ctxt->xpathCtxt->contextSize;
     oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
     oldNsNr = ctxt->xpathCtxt->nsNr;
@@ -124,6 +130,12 @@ xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
     int oldNsNr;
     xmlNsPtr *oldNamespaces;
 
+    if ((ctxt == NULL) || (ctxt->inst == NULL)) {
+        xsltTransformError(ctxt, NULL, NULL,
+            "xsltEvalXPathStringNs: No context or instruction\n");
+        return(0);
+    }
+
     oldInst = ctxt->inst;
     oldNode = ctxt->node;
     oldPos = ctxt->xpathCtxt->proximityPosition;
diff --git a/tests/docs/bug-200.xml b/tests/docs/bug-200.xml
new file mode 100644
index 0000000..69d62f2
--- /dev/null
+++ b/tests/docs/bug-200.xml
@@ -0,0 +1 @@
+<doc/>
diff --git a/tests/general/bug-200.out b/tests/general/bug-200.out
new file mode 100644
index 0000000..71afb61
--- /dev/null
+++ b/tests/general/bug-200.out
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+found
diff --git a/tests/general/bug-200.xsl b/tests/general/bug-200.xsl
new file mode 100644
index 0000000..8aad8b5
--- /dev/null
+++ b/tests/general/bug-200.xsl
@@ -0,0 +1,5 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">
+  <template xmlns="http://www.w3.org/1999/XSL/Transform"; match="*[element-available('apply-templates')]">
+    <text>found</text>
+  </template>
+</xsl:stylesheet>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]