summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2017-01-30 08:52:32 -0800
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2017-01-30 11:51:07 -0800
commitbc1e444694427d599710107d3e6b62165380b0b6 (patch)
tree7676f5aa9ff7b4b77d48f281b569710b46865e00
parent298996df11381fcd3b87ddd02d7b4fef2a62b86e (diff)
XPath: Track allocation errors more explicitly
Any time an allocation fails xpath_allocator can set an externally provided bool. The plan is to keep this bool up until evaluation ends, so that we can use it to discard the potentially malformed result.
-rw-r--r--src/pugixml.cpp28
1 files changed, 20 insertions, 8 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 6b9fc89..396061a 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -7396,13 +7396,14 @@ PUGI__NS_BEGIN
{
xpath_memory_block* _root;
size_t _root_size;
+ bool* _error;
public:
#ifdef PUGIXML_NO_EXCEPTIONS
jmp_buf* error_handler;
#endif
- xpath_allocator(xpath_memory_block* root, size_t root_size = 0): _root(root), _root_size(root_size)
+ xpath_allocator(xpath_memory_block* root, bool* error = 0): _root(root), _root_size(0), _error(error)
{
#ifdef PUGIXML_NO_EXCEPTIONS
error_handler = 0;
@@ -7430,7 +7431,11 @@ PUGI__NS_BEGIN
size_t block_size = block_capacity + offsetof(xpath_memory_block, data);
xpath_memory_block* block = static_cast<xpath_memory_block*>(xml_memory::allocate(block_size));
- if (!block) return 0;
+ if (!block)
+ {
+ if (_error) *_error = true;
+ return 0;
+ }
block->next = _root;
block->capacity = block_capacity;
@@ -7579,6 +7584,7 @@ PUGI__NS_BEGIN
struct xpath_stack_data
{
+ bool error;
xpath_memory_block blocks[2];
xpath_allocator result;
xpath_allocator temp;
@@ -7588,7 +7594,7 @@ PUGI__NS_BEGIN
jmp_buf error_handler;
#endif
- xpath_stack_data(): result(blocks + 0), temp(blocks + 1)
+ xpath_stack_data(): error(false), result(blocks + 0, &error), temp(blocks + 1, &error)
{
blocks[0].next = blocks[1].next = 0;
blocks[0].capacity = blocks[1].capacity = sizeof(blocks[0].data);
@@ -11856,7 +11862,9 @@ PUGI__NS_BEGIN
xpath_context c(n, 1, 1);
- return impl->root->eval_string(c, sd.stack);
+ xpath_string r = impl->root->eval_string(c, sd.stack);
+
+ return sd.error ? xpath_string() : r;
}
PUGI__FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl)
@@ -12494,7 +12502,9 @@ namespace pugi
if (setjmp(sd.error_handler)) return false;
#endif
- return static_cast<impl::xpath_query_impl*>(_impl)->root->eval_boolean(c, sd.stack);
+ bool r = static_cast<impl::xpath_query_impl*>(_impl)->root->eval_boolean(c, sd.stack);
+
+ return sd.error ? false : r;
}
PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const
@@ -12508,7 +12518,9 @@ namespace pugi
if (setjmp(sd.error_handler)) return impl::gen_nan();
#endif
- return static_cast<impl::xpath_query_impl*>(_impl)->root->eval_number(c, sd.stack);
+ double r = static_cast<impl::xpath_query_impl*>(_impl)->root->eval_number(c, sd.stack);
+
+ return sd.error ? impl::gen_nan() : r;
}
#ifndef PUGIXML_NO_STL
@@ -12556,7 +12568,7 @@ namespace pugi
impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all);
- return xpath_node_set(r.begin(), r.end(), r.type());
+ return sd.error ? xpath_node_set() : xpath_node_set(r.begin(), r.end(), r.type());
}
PUGI__FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const
@@ -12573,7 +12585,7 @@ namespace pugi
impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first);
- return r.first();
+ return sd.error ? xpath_node() : r.first();
}
PUGI__FN const xpath_parse_result& xpath_query::result() const