aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2021-05-11 22:45:30 -0700
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2021-05-11 22:53:54 -0700
commit8cece4b9fe2db68e6ae1dc725e438268feae93a4 (patch)
tree026b1b8dc23e98ab5cf061150079e708040d974c
parent56c9afa7c8841641d7f5719eeb2e275ebfed8657 (diff)
downloadpugixml-8cece4b9fe2db68e6ae1dc725e438268feae93a4.zip
pugixml-8cece4b9fe2db68e6ae1dc725e438268feae93a4.tar.gz
pugixml-8cece4b9fe2db68e6ae1dc725e438268feae93a4.tar.bz2
Fix a bug in move construction when move source is empty
Previously when copying the allocator state we would copy an incorrect root pointer into the document's current state; while this had a minimal impact on the allocation state due to the fact that any new allocation would need to create a new page, this used a potentially stale field of the moved document when setting up new pages, which could create issues in future uses of the pages. This change fixes the core problem and also removes the use of the _root->allocator from allocate_page since it's not clear why we need it there in the first place.
-rw-r--r--src/pugixml.cpp11
-rw-r--r--tests/test_document.cpp11
2 files changed, 19 insertions, 3 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 13b9504..2b365d9 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -526,7 +526,8 @@ PUGI__NS_BEGIN
xml_memory_page* page = xml_memory_page::construct(memory);
assert(page);
- page->allocator = _root->allocator;
+ assert(this == _root->allocator);
+ page->allocator = this;
return page;
}
@@ -7091,8 +7092,12 @@ namespace pugi
#endif
// move allocation state
- doc->_root = other->_root;
- doc->_busy_size = other->_busy_size;
+ // note that other->_root may point to the embedded document page, in which case we should keep original (empty) state
+ if (other->_root != PUGI__GETPAGE(other))
+ {
+ doc->_root = other->_root;
+ doc->_busy_size = other->_busy_size;
+ }
// move buffer state
doc->buffer = other->buffer;
diff --git a/tests/test_document.cpp b/tests/test_document.cpp
index 8ed2e21..e853b61 100644
--- a/tests/test_document.cpp
+++ b/tests/test_document.cpp
@@ -1806,4 +1806,15 @@ TEST(document_move_compact_fail)
CHECK(!docs[safe_count+1].first_child());
}
#endif
+
+TEST(document_move_assign_empty)
+{
+ xml_document doc;
+ doc.append_child(STR("node"));
+
+ doc = xml_document();
+ doc.append_child(STR("node2"));
+
+ CHECK_NODE(doc, "<node2/>");
+}
#endif