summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2014-11-05 09:32:52 +0100
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2014-11-05 09:32:52 +0100
commitaa1a61c59f2064592d3000a241b01f7ff4bbe0a8 (patch)
tree82a4464f6219b9389c1f34471afb4aa1d1b33bc5
parentab12b30c838fd95f1bc8f6fb15ba2380294aec41 (diff)
Fix xml_node::offset_debug for corner cases
Computed offsets for documents with nodes that were added using append_buffer or newly appended nodes without name/value information were invalid.
-rw-r--r--src/pugixml.cpp8
-rw-r--r--tests/test_dom_traverse.cpp37
2 files changed, 41 insertions, 4 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 973cfd6..3fe492b 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -5402,8 +5402,8 @@ namespace pugi
impl::xml_document_struct& doc = impl::get_document(_root);
- const char_t* buffer = doc.buffer;
- if (!buffer) return -1;
+ // we can determine the offset reliably only if there is exactly once parse buffer
+ if (!doc.buffer || doc.extra_buffers) return -1;
switch (type())
{
@@ -5413,13 +5413,13 @@ namespace pugi
case node_element:
case node_declaration:
case node_pi:
- return (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) ? -1 : _root->name - buffer;
+ return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1;
case node_pcdata:
case node_cdata:
case node_comment:
case node_doctype:
- return (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) ? -1 : _root->value - buffer;
+ return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1;
default:
return -1;
diff --git a/tests/test_dom_traverse.cpp b/tests/test_dom_traverse.cpp
index 83afec8..721a079 100644
--- a/tests/test_dom_traverse.cpp
+++ b/tests/test_dom_traverse.cpp
@@ -924,6 +924,43 @@ TEST_XML_FLAGS(dom_offset_debug, "<?xml?><!DOCTYPE><?pi?><!--comment--><node>pcd
CHECK((cit++)->offset_debug() == 58);
}
+TEST(dom_offset_debug_encoding)
+{
+ char buf[] = { 0, '<', 0, 'n', 0, '/', 0, '>' };
+
+ xml_document doc;
+ CHECK(doc.load_buffer(buf, sizeof(buf)));
+
+ CHECK(doc.offset_debug() == 0);
+ CHECK(doc.first_child().offset_debug() == 1);
+}
+
+TEST_XML(dom_offset_debug_append, "<node/>")
+{
+ xml_node c1 = doc.first_child();
+ xml_node c2 = doc.append_child(STR("node"));
+ xml_node c3 = doc.append_child(node_pcdata);
+
+ CHECK(doc.offset_debug() == 0);
+ CHECK(c1.offset_debug() == 1);
+ CHECK(c2.offset_debug() == -1);
+ CHECK(c3.offset_debug() == -1);
+
+ c1.set_name(STR("nodenode"));
+ CHECK(c1.offset_debug() == -1);
+}
+
+TEST_XML(dom_offset_debug_append_buffer, "<node/>")
+{
+ CHECK(doc.offset_debug() == 0);
+ CHECK(doc.first_child().offset_debug() == 1);
+
+ CHECK(doc.append_buffer("<node/>", 7));
+ CHECK(doc.offset_debug() == -1);
+ CHECK(doc.first_child().offset_debug() == -1);
+ CHECK(doc.last_child().offset_debug() == -1);
+}
+
TEST_XML(dom_internal_object, "<node attr='value'>value</node>")
{
xml_node node = doc.child(STR("node"));