aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2022-05-16 20:50:07 -0700
committerGitHub <noreply@github.com>2022-05-16 20:50:07 -0700
commit0401559dde98bbc8f50572d3fcd402141132ad7a (patch)
tree48e23cb26afb350c735de268bb5aea6384705067
parentec851bb18df651a5ac9279f72daae447b63a96aa (diff)
parent832a4f4914cc7830b1a7ec675b1c84290bdf2808 (diff)
downloadpugixml-0401559dde98bbc8f50572d3fcd402141132ad7a.zip
pugixml-0401559dde98bbc8f50572d3fcd402141132ad7a.tar.gz
pugixml-0401559dde98bbc8f50572d3fcd402141132ad7a.tar.bz2
Merge pull request #498 from zeux/fix-oom-safer
Fix memory leak during OOM in convert_buffer
-rw-r--r--src/pugixml.cpp12
-rw-r--r--tests/test_document.cpp36
2 files changed, 43 insertions, 5 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 13781e1..47764c8 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -4707,16 +4707,18 @@ PUGI__NS_BEGIN
// get actual encoding
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
+ // if convert_buffer below throws bad_alloc, we still need to deallocate contents if we own it
+ auto_deleter<void> contents_guard(own ? contents : 0, xml_memory::deallocate);
+
// get private buffer
char_t* buffer = 0;
size_t length = 0;
// coverity[var_deref_model]
- if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable))
- {
- if (own && contents) impl::xml_memory::deallocate(contents);
- return impl::make_parse_result(status_out_of_memory);
- }
+ if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
+
+ // after this we either deallocate contents (below) or hold on to it via doc->buffer, so we don't need to guard it
+ contents_guard.release();
// delete original buffer if we performed a conversion
if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
diff --git a/tests/test_document.cpp b/tests/test_document.cpp
index 5379092..0e0bad4 100644
--- a/tests/test_document.cpp
+++ b/tests/test_document.cpp
@@ -1817,3 +1817,39 @@ TEST(document_move_assign_empty)
CHECK_NODE(doc, STR("<node2/>"));
}
#endif
+
+TEST(document_load_buffer_convert_out_of_memory)
+{
+ const char* source = "<node>\xe7</node>";
+ size_t size = strlen(source);
+
+ test_runner::_memory_fail_threshold = 1;
+
+ xml_document doc;
+
+ xml_parse_result result;
+ result.status = status_out_of_memory;
+ CHECK_ALLOC_FAIL(result = doc.load_buffer(source, size, pugi::parse_default, pugi::encoding_latin1));
+
+ CHECK(result.status == status_out_of_memory);
+}
+
+TEST(document_load_buffer_own_convert_out_of_memory)
+{
+ const char* source = "<node>\xe7</node>";
+ size_t size = strlen(source);
+
+ void* buffer = pugi::get_memory_allocation_function()(size);
+ CHECK(buffer);
+ memcpy(buffer, source, size);
+
+ test_runner::_memory_fail_threshold = 1;
+
+ xml_document doc;
+
+ xml_parse_result result;
+ result.status = status_out_of_memory;
+ CHECK_ALLOC_FAIL(result = doc.load_buffer_inplace_own(buffer, size, pugi::parse_default, pugi::encoding_latin1));
+
+ CHECK(result.status == status_out_of_memory);
+}