[libxslt] Fix saxon:line-number with namespace nodes



commit 8b90c9a699e0eaa98bbeec63a473ddc73aaa238c
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Apr 26 17:29:05 2016 +0200

    Fix saxon:line-number with namespace nodes
    
    exsltSaxonLineNumberFunction must make sure not to pass namespace
    "nodes" to xmlGetLineNo. Otherwise, an OOB heap read results which
    typically leads to a segfault.
    
    Found with afl-fuzz and ASan.

 libexslt/saxon.c               |   45 ++++++++++++++++++++++++++-------------
 tests/exslt/saxon/Makefile.am  |    3 +-
 tests/exslt/saxon/lineno.1.out |    6 +++++
 tests/exslt/saxon/lineno.1.xml |    9 ++++++++
 tests/exslt/saxon/lineno.1.xsl |   24 +++++++++++++++++++++
 5 files changed, 71 insertions(+), 16 deletions(-)
---
diff --git a/libexslt/saxon.c b/libexslt/saxon.c
index 491b31b..7a2f63b 100644
--- a/libexslt/saxon.c
+++ b/libexslt/saxon.c
@@ -229,11 +229,12 @@ exsltSaxonSystemIdFunction(xmlXPathParserContextPtr ctxt, int nargs)
 static void
 exsltSaxonLineNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
     xmlNodePtr cur = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    long lineNo = -1;
 
     if (nargs == 0) {
        cur = ctxt->context->node;
     } else if (nargs == 1) {
-       xmlXPathObjectPtr obj;
        xmlNodeSetPtr nodelist;
        int i;
 
@@ -246,18 +247,14 @@ exsltSaxonLineNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
 
        obj = valuePop(ctxt);
        nodelist = obj->nodesetval;
-       if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
-           xmlXPathFreeObject(obj);
-           valuePush(ctxt, xmlXPathNewFloat(-1));
-           return;
-       }
-       cur = nodelist->nodeTab[0];
-       for (i = 1;i < nodelist->nodeNr;i++) {
-           int ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
-           if (ret == -1)
-               cur = nodelist->nodeTab[i];
-       }
-       xmlXPathFreeObject(obj);
+       if ((nodelist != NULL) && (nodelist->nodeNr > 0)) {
+            cur = nodelist->nodeTab[0];
+            for (i = 1;i < nodelist->nodeNr;i++) {
+                int ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
+                if (ret == -1)
+                    cur = nodelist->nodeTab[i];
+            }
+        }
     } else {
        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                "saxon:line-number() : invalid number of args %d\n",
@@ -266,8 +263,26 @@ exsltSaxonLineNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
        return;
     }
 
-    valuePush(ctxt, xmlXPathNewFloat(xmlGetLineNo(cur)));
-    return;
+    if ((cur != NULL) && (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 exsltSaxonLineNumberFunction: "
+                "Cannot retrieve the doc of a namespace node.\n");
+            cur = NULL;
+        }
+    }
+
+    if (cur != NULL)
+        lineNo = xmlGetLineNo(cur);
+
+    valuePush(ctxt, xmlXPathNewFloat(lineNo));
+
+    xmlXPathFreeObject(obj);
 }
 
 /**
diff --git a/tests/exslt/saxon/Makefile.am b/tests/exslt/saxon/Makefile.am
index 8535633..22d6b62 100644
--- a/tests/exslt/saxon/Makefile.am
+++ b/tests/exslt/saxon/Makefile.am
@@ -6,7 +6,8 @@ $(top_builddir)/xsltproc/xsltproc:
 EXTRA_DIST =                                           \
        eval.1.out      eval.1.xml      eval.1.xsl      \
        eval.2.out      eval.2.xml      eval.2.xsl      \
-       eval.3.out      eval.3.xml      eval.3.xsl
+       eval.3.out      eval.3.xml      eval.3.xsl      \
+       lineno.1.out    lineno.1.xml    lineno.1.xsl
 
 CLEANFILES = .memdump
 
diff --git a/tests/exslt/saxon/lineno.1.out b/tests/exslt/saxon/lineno.1.out
new file mode 100644
index 0000000..3350b08
--- /dev/null
+++ b/tests/exslt/saxon/lineno.1.out
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<results>
+  <lineno>1</lineno>
+  <lineno>8</lineno>
+  <lineno>8</lineno>
+</results>
diff --git a/tests/exslt/saxon/lineno.1.xml b/tests/exslt/saxon/lineno.1.xml
new file mode 100644
index 0000000..5b05110
--- /dev/null
+++ b/tests/exslt/saxon/lineno.1.xml
@@ -0,0 +1,9 @@
+<doc>
+    <!--
+        a
+        couple
+        of
+        lines
+    -->
+    <elem/>
+</doc>
diff --git a/tests/exslt/saxon/lineno.1.xsl b/tests/exslt/saxon/lineno.1.xsl
new file mode 100644
index 0000000..909a93e
--- /dev/null
+++ b/tests/exslt/saxon/lineno.1.xsl
@@ -0,0 +1,24 @@
+<xsl:stylesheet
+    version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+    xmlns:saxon="http://icl.com/saxon";
+    exclude-result-prefixes="saxon">
+
+<xsl:output indent="yes"/>
+
+<xsl:template match="/">
+    <results>
+        <lineno>
+            <xsl:value-of select="saxon:line-number(/doc)"/>
+        </lineno>
+        <lineno>
+            <xsl:value-of select="saxon:line-number(/doc/elem)"/>
+        </lineno>
+        <lineno>
+            <xsl:value-of select="saxon:line-number(/doc/elem/namespace::*)"/>
+        </lineno>
+    </results>
+</xsl:template>
+
+</xsl:stylesheet>
+


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