[libxml2] Fix axis traversal from attribute and namespace nodes
- From: Nick Wellnhofer <nwellnhof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml2] Fix axis traversal from attribute and namespace nodes
- Date: Thu, 1 Jun 2017 13:01:33 +0000 (UTC)
commit 40f58521493e6a5429ea92964dec7bc09168224f
Author: Nick Wellnhofer <wellnhofer aevum de>
Date: Fri May 26 20:16:35 2017 +0200
Fix axis traversal from attribute and namespace nodes
When traversing the "preceding" axis from an attribute node, we must
first go up to the attribute's containing element. Otherwise, text
children of other attributes could be returned. This made it possible
to hit a code path in xmlXPathNextAncestor which contained another bug:
The attribute node was initialized with the context node instead of the
current node. Normally, this code path is only hit via
xmlXPathNextAncestorOrSelf in which case the current and context node
are the same.
The combination of the two bugs could result in an infinite loop, found
with libFuzzer.
Traversing the "following" and the "preceding" axis from namespace nodes
should be handled similarly. This wasn't supported at all previously.
result/XPath/tests/nssimple | 18 +++++++++++++++-
result/XPath/tests/simplebase | 5 ++++
test/XPath/docs/ns | 2 +
test/XPath/tests/nssimple | 2 +
test/XPath/tests/simplebase | 1 +
xpath.c | 42 ++++++++++++++++++++++++++++++----------
6 files changed, 57 insertions(+), 13 deletions(-)
---
diff --git a/result/XPath/tests/nssimple b/result/XPath/tests/nssimple
index 8f0dd0e..cd09a17 100644
--- a/result/XPath/tests/nssimple
+++ b/result/XPath/tests/nssimple
@@ -17,8 +17,22 @@ Set contains 3 nodes:
========================
Expression: //*[namespace::ns1]
Object is a Node Set :
-Set contains 2 nodes:
+Set contains 4 nodes:
1 ELEMENT doc
namespace ns1 href=nsuri1
-2 ELEMENT elem
+2 ELEMENT preceding
+3 ELEMENT elem
namespace ns2 href=nsuri2
+4 ELEMENT following
+
+========================
+Expression: /doc/elem/namespace::ns2/following::*
+Object is a Node Set :
+Set contains 1 nodes:
+1 ELEMENT following
+
+========================
+Expression: /doc/elem/namespace::ns2/preceding::*
+Object is a Node Set :
+Set contains 1 nodes:
+1 ELEMENT preceding
diff --git a/result/XPath/tests/simplebase b/result/XPath/tests/simplebase
index 3c32d17..6d4b347 100644
--- a/result/XPath/tests/simplebase
+++ b/result/XPath/tests/simplebase
@@ -125,3 +125,8 @@ Expression: /descendant::p/ancestor::chapter
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT chapter
+
+========================
+Expression: /child::EXAMPLE/attribute::prop2/preceding::text()
+Object is a Node Set :
+Set contains 0 nodes:
diff --git a/test/XPath/docs/ns b/test/XPath/docs/ns
index 88f4575..2338a6f 100644
--- a/test/XPath/docs/ns
+++ b/test/XPath/docs/ns
@@ -1,3 +1,5 @@
<doc xmlns:ns1="nsuri1">
+ <preceding/>
<elem xmlns:ns2="nsuri2"/>
+ <following/>
</doc>
diff --git a/test/XPath/tests/nssimple b/test/XPath/tests/nssimple
index d2a9528..8b343a3 100644
--- a/test/XPath/tests/nssimple
+++ b/test/XPath/tests/nssimple
@@ -1,3 +1,5 @@
/doc/elem/namespace::node()/..
/doc/elem/namespace::*/self::node()[true()]
//*[namespace::ns1]
+/doc/elem/namespace::ns2/following::*
+/doc/elem/namespace::ns2/preceding::*
diff --git a/test/XPath/tests/simplebase b/test/XPath/tests/simplebase
index 8b2c7d1..7b302af 100644
--- a/test/XPath/tests/simplebase
+++ b/test/XPath/tests/simplebase
@@ -13,3 +13,4 @@
/child::EXAMPLE/attribute::prop1/ancestor-or-self::*
/descendant::title
/descendant::p/ancestor::chapter
+/child::EXAMPLE/attribute::prop2/preceding::text()
diff --git a/xpath.c b/xpath.c
index 6f4da78..dce1107 100644
--- a/xpath.c
+++ b/xpath.c
@@ -8135,12 +8135,12 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
return(NULL);
return(cur->parent);
case XML_ATTRIBUTE_NODE: {
- xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
+ xmlAttrPtr att = (xmlAttrPtr) cur;
return(att->parent);
}
case XML_NAMESPACE_DECL: {
- xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
+ xmlNsPtr ns = (xmlNsPtr) cur;
if ((ns->next != NULL) &&
(ns->next->type != XML_NAMESPACE_DECL))
@@ -8257,10 +8257,16 @@ xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (cur == NULL) {
cur = ctxt->context->node;
- if (cur->type == XML_NAMESPACE_DECL)
- return(NULL);
- if (cur->type == XML_ATTRIBUTE_NODE)
+ if (cur->type == XML_ATTRIBUTE_NODE) {
cur = cur->parent;
+ } else if (cur->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) cur;
+
+ if ((ns->next == NULL) ||
+ (ns->next->type == XML_NAMESPACE_DECL))
+ return (NULL);
+ cur = (xmlNodePtr) ns->next;
+ }
}
if (cur == NULL) return(NULL) ; /* ERROR */
if (cur->next != NULL) return(cur->next) ;
@@ -8321,10 +8327,16 @@ xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
if (cur == NULL) {
cur = ctxt->context->node;
- if (cur->type == XML_NAMESPACE_DECL)
- return(NULL);
- if (cur->type == XML_ATTRIBUTE_NODE)
- return(cur->parent);
+ if (cur->type == XML_ATTRIBUTE_NODE) {
+ cur = cur->parent;
+ } else if (cur->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) cur;
+
+ if ((ns->next == NULL) ||
+ (ns->next->type == XML_NAMESPACE_DECL))
+ return (NULL);
+ cur = (xmlNodePtr) ns->next;
+ }
}
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
return (NULL);
@@ -8369,8 +8381,16 @@ xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
cur = ctxt->context->node;
if (cur == NULL)
return (NULL);
- if (cur->type == XML_NAMESPACE_DECL)
- return (NULL);
+ if (cur->type == XML_ATTRIBUTE_NODE) {
+ cur = cur->parent;
+ } else if (cur->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) cur;
+
+ if ((ns->next == NULL) ||
+ (ns->next->type == XML_NAMESPACE_DECL))
+ return (NULL);
+ cur = (xmlNodePtr) ns->next;
+ }
ctxt->ancestor = cur->parent;
}
if (cur->type == XML_NAMESPACE_DECL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]