[libxslt] Fix dyn:map with namespace nodes



commit 93bb314768aafaffad1df15bbee10b7c5423e283
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Apr 26 15:39:06 2016 +0200

    Fix dyn:map with namespace nodes
    
    exsltDynMapFunction didn't handle namespace nodes correctly. Namespace
    nodes are actually an xmlNs, not an xmlNode and must be special-cased.
    
    The old code initialized the doc pointer in the XPath context struct
    with a value read from past the end of the xmlNs struct. Typically,
    this resulted in a segfault.
    
    Found with afl-fuzz and ASan.

 libexslt/dynamic.c             |   21 +++++++++++++++++++--
 tests/exslt/dynamic/dynmap.out |    3 +++
 tests/exslt/dynamic/dynmap.xsl |    3 +++
 3 files changed, 25 insertions(+), 2 deletions(-)
---
diff --git a/libexslt/dynamic.c b/libexslt/dynamic.c
index e0bfe81..7b95fc5 100644
--- a/libexslt/dynamic.c
+++ b/libexslt/dynamic.c
@@ -167,10 +167,27 @@ exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
         ctxt->context->proximityPosition = 0;
         for (i = 0; i < nodeset->nodeNr; i++) {
             xmlXPathObjectPtr subResult = NULL;
+            xmlNodePtr cur = nodeset->nodeTab[i];
 
             ctxt->context->proximityPosition++;
-            ctxt->context->node = nodeset->nodeTab[i];
-            ctxt->context->doc = nodeset->nodeTab[i]->doc;
+            ctxt->context->node = cur;
+
+            if (cur->type == XML_NAMESPACE_DECL) {
+                /*
+                * The XPath module sets the owner element of a ns-node on
+                * the ns->next field.
+                */
+                cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
+                if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
+                    xsltGenericError(xsltGenericErrorContext,
+                        "Internal error in exsltDynMapFunction: "
+                        "Cannot retrieve the doc of a namespace node.\n");
+                    continue;
+                }
+                ctxt->context->doc = cur->doc;
+            } else {
+                ctxt->context->doc = cur->doc;
+            }
 
             subResult = xmlXPathCompiledEval(comp, ctxt->context);
             if (subResult != NULL) {
diff --git a/tests/exslt/dynamic/dynmap.out b/tests/exslt/dynamic/dynmap.out
index b75b87c..7a900ca 100644
--- a/tests/exslt/dynamic/dynmap.out
+++ b/tests/exslt/dynamic/dynmap.out
@@ -38,4 +38,7 @@
     <exsl:string xmlns:exsl="http://exslt.org/common";>without-child</exsl:string>
     <exsl:string xmlns:exsl="http://exslt.org/common";>with-child</exsl:string>
   </string>
+  <namespace>
+    <exsl:string xmlns:exsl="http://exslt.org/common";>dynmap</exsl:string>
+  </namespace>
 </result>
diff --git a/tests/exslt/dynamic/dynmap.xsl b/tests/exslt/dynamic/dynmap.xsl
index bfcef58..40f9eaf 100644
--- a/tests/exslt/dynamic/dynmap.xsl
+++ b/tests/exslt/dynamic/dynmap.xsl
@@ -18,6 +18,9 @@
  <string>
   <xsl:copy-of select="dyn:map(*, 'name()')"/>
  </string>  
+ <namespace>
+  <xsl:copy-of select="dyn:map(namespace::*, 'name(/*)')"/>
+ </namespace>
 </result> 
 </xsl:template>
 </xsl:stylesheet>


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