0
0
mirror of https://github.com/zeux/pugixml.git synced 2024-12-26 21:04:25 +08:00

XPath: Correct out of memory handling for string to number conversion during parsing, added corresponding test

git-svn-id: http://pugixml.googlecode.com/svn/trunk@651 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
arseny.kapoulkine 2010-08-29 15:16:55 +00:00
parent 6a9d59e907
commit 1f74bf1edc
2 changed files with 31 additions and 23 deletions

View File

@ -497,35 +497,30 @@ namespace
#endif
}
double convert_string_to_number(const char_t* begin, const char_t* end)
bool convert_string_to_number(const char_t* begin, const char_t* end, double* out_result)
{
char_t buffer[32];
size_t length = static_cast<size_t>(end - begin);
char_t* scratch = buffer;
if (length < sizeof(buffer) / sizeof(buffer[0]))
{
// optimized on-stack conversion
memcpy(buffer, begin, length * sizeof(char_t));
buffer[length] = 0;
return convert_string_to_number(buffer);
}
else
if (length >= sizeof(buffer) / sizeof(buffer[0]))
{
// need to make dummy on-heap copy
char_t* copy = static_cast<char_t*>(get_memory_allocation_function()((length + 1) * sizeof(char_t)));
if (!copy) return gen_nan(); // $$ out of memory
memcpy(copy, begin, length * sizeof(char_t));
copy[length] = 0;
double result = convert_string_to_number(copy);
get_memory_deallocation_function()(copy);
return result;
scratch = static_cast<char_t*>(get_memory_allocation_function()((length + 1) * sizeof(char_t)));
if (!scratch) return false;
}
// copy string to zero-terminated buffer and perform conversion
memcpy(scratch, begin, length * sizeof(char_t));
scratch[length] = 0;
*out_result = convert_string_to_number(scratch);
// free dummy buffer
if (scratch != buffer) get_memory_deallocation_function()(scratch);
return true;
}
double round_nearest(double value)
@ -2899,7 +2894,10 @@ namespace pugi
case lex_number:
{
double value = convert_string_to_number(_lexer.contents().begin, _lexer.contents().end);
double value = 0;
if (!convert_string_to_number(_lexer.contents().begin, _lexer.contents().end, &value))
throw_error("Out of memory");
xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value);
_lexer.next();

View File

@ -269,15 +269,25 @@ TEST_XML(xpath_parse_absolute, "<div><s/></div>")
CHECK_XPATH_NODESET(doc, STR("/*[/]")) % 2;
}
TEST(xpath_parse_out_of_memory)
TEST(xpath_parse_out_of_memory_first_page)
{
test_runner::_memory_fail_threshold = 1;
CHECK_XPATH_FAIL(STR("1"));
}
TEST(xpath_parse_out_of_memory_second_page_node)
{
test_runner::_memory_fail_threshold = 8192;
CHECK_XPATH_FAIL(STR("1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1"));
}
TEST(xpath_parse_out_of_memory_string_to_number)
{
test_runner::_memory_fail_threshold = 4096 + 128;
CHECK_XPATH_FAIL(STR("0.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"));
}
#endif