aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2020-09-11 09:50:41 -0700
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2020-09-11 09:50:41 -0700
commit8e5b8e0f460587dcc596be0cde6e6441d15b29e1 (patch)
tree98295faebdf09f1c2ff2108dafdb02d25a375cad
parent20aef1cd4b436a8859a54b41cc992db517c61d2d (diff)
downloadpugixml-8e5b8e0f460587dcc596be0cde6e6441d15b29e1.zip
pugixml-8e5b8e0f460587dcc596be0cde6e6441d15b29e1.tar.gz
pugixml-8e5b8e0f460587dcc596be0cde6e6441d15b29e1.tar.bz2
XPath: Fix stack overflow in functions with long argument lists
Function call arguments are stored in a list which is processed recursively during optimize(). We now limit the depth of this construct as well to make sure optimize() doesn't run out of stack space.
-rw-r--r--src/pugixml.cpp7
-rw-r--r--tests/test_xpath_parse.cpp1
2 files changed, 8 insertions, 0 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index e166458..5a665a3 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -11541,6 +11541,8 @@ PUGI__NS_BEGIN
return error("Unrecognized function call");
_lexer.next();
+ size_t old_depth = _depth;
+
while (_lexer.current() != lex_close_brace)
{
if (argc > 0)
@@ -11550,6 +11552,9 @@ PUGI__NS_BEGIN
_lexer.next();
}
+ if (++_depth > xpath_ast_depth_limit)
+ return error_rec();
+
xpath_ast_node* n = parse_expression();
if (!n) return 0;
@@ -11562,6 +11567,8 @@ PUGI__NS_BEGIN
_lexer.next();
+ _depth = old_depth;
+
return parse_function(function, argc, args);
}
diff --git a/tests/test_xpath_parse.cpp b/tests/test_xpath_parse.cpp
index d0b0bac..494b0ae 100644
--- a/tests/test_xpath_parse.cpp
+++ b/tests/test_xpath_parse.cpp
@@ -401,6 +401,7 @@ TEST(xpath_parse_depth_limit)
CHECK_XPATH_FAIL((STR("/foo") + rep(STR("[1]"), limit)).c_str());
CHECK_XPATH_FAIL((STR("/foo") + rep(STR("/x"), limit)).c_str());
CHECK_XPATH_FAIL((STR("1") + rep(STR("+1"), limit)).c_str());
+ CHECK_XPATH_FAIL((STR("concat(") + rep(STR("1,"), limit) + STR("1)")).c_str());
}
TEST_XML(xpath_parse_location_path, "<node><child/></node>")