diff options
author | Tor Brede Vekterli <vekterli@verizonmedia.com> | 2020-04-01 11:21:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-01 11:21:16 +0200 |
commit | be3c2e7f0f1f3edc07973dccb05b13bf30c75de1 (patch) | |
tree | 710db4b6b95bf5bda839070b952d380591126f7e /document/src/tests/documentselectparsertest.cpp | |
parent | 444693a52467663ba4195e4f90991a388defe75c (diff) | |
parent | 4153969ca13541e7434963d02add12d574c9a461 (diff) |
Merge pull request #12784 from vespa-engine/vekterli/add-explicit-limits-to-selection-parser
Add explicit limits to backend document selection parsing
Diffstat (limited to 'document/src/tests/documentselectparsertest.cpp')
-rw-r--r-- | document/src/tests/documentselectparsertest.cpp | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/document/src/tests/documentselectparsertest.cpp b/document/src/tests/documentselectparsertest.cpp index 110153954af..59f4ce69b33 100644 --- a/document/src/tests/documentselectparsertest.cpp +++ b/document/src/tests/documentselectparsertest.cpp @@ -18,6 +18,7 @@ #include <vespa/document/select/compare.h> #include <vespa/document/select/operator.h> #include <vespa/document/select/parse_utils.h> +#include <vespa/document/select/parser_limits.h> #include <vespa/vespalib/util/exceptions.h> #include <limits> #include <gtest/gtest.h> @@ -1247,17 +1248,17 @@ TEST_F(DocumentSelectParserTest, testThatSimpleFieldValuesHaveCorrectFieldName) TEST_F(DocumentSelectParserTest, testThatComplexFieldValuesHaveCorrectFieldNames) { - EXPECT_EQ( - vespalib::string("headerval"), - parseFieldValue("testdoctype1.headerval{test}")->getRealFieldName()); + EXPECT_EQ(vespalib::string("headerval"), + parseFieldValue("testdoctype1.headerval{test}")->getRealFieldName()); - EXPECT_EQ( - vespalib::string("headerval"), - parseFieldValue("testdoctype1.headerval[42]")->getRealFieldName()); + EXPECT_EQ(vespalib::string("headerval"), + parseFieldValue("testdoctype1.headerval[42]")->getRealFieldName()); - EXPECT_EQ( - vespalib::string("headerval"), - parseFieldValue("testdoctype1.headerval.meow.meow{test}")->getRealFieldName()); + EXPECT_EQ(vespalib::string("headerval"), + parseFieldValue("testdoctype1.headerval.meow.meow{test}")->getRealFieldName()); + + EXPECT_EQ(vespalib::string("headerval"), + parseFieldValue("testdoctype1.headerval .meow.meow{test}")->getRealFieldName()); } namespace { @@ -1603,4 +1604,64 @@ TEST_F(DocumentSelectParserTest, redundant_glob_wildcards_are_collapsed_into_min EXPECT_EQ(GlobOperator::convertToRegex("*?*?*?*"), "..*..*."); // Don't try this at home, kids! } +TEST_F(DocumentSelectParserTest, recursion_depth_is_bounded_for_field_exprs) { + createDocs(); + std::string expr = "testdoctype1"; + for (size_t i = 0; i < 50000; ++i) { + expr += ".foo"; + } + expr += ".hash() != 0"; + verifyFailedParse(expr, "ParsingFailedException: expression is too deeply nested (max 1024 levels)"); +} + +TEST_F(DocumentSelectParserTest, recursion_depth_is_bounded_for_arithmetic_exprs) { + createDocs(); + std::string expr = "1"; + for (size_t i = 0; i < 50000; ++i) { + expr += "+1"; + } + expr += " != 0"; + verifyFailedParse(expr, "ParsingFailedException: expression is too deeply nested (max 1024 levels)"); +} + +TEST_F(DocumentSelectParserTest, recursion_depth_is_bounded_for_binary_logical_exprs) { + createDocs(); + // Also throw in some comparisons to ensure they carry over the max depth. + std::string expr = "1 == 2"; + std::string cmp_subexpr = "3 != 4"; + for (size_t i = 0; i < 10000; ++i) { + expr += (i % 2 == 0 ? " and " : " or ") + cmp_subexpr; + } + verifyFailedParse(expr, "ParsingFailedException: expression is too deeply nested (max 1024 levels)"); +} + +TEST_F(DocumentSelectParserTest, recursion_depth_is_bounded_for_unary_logical_exprs) { + createDocs(); + std::string expr; + for (size_t i = 0; i < 10000; ++i) { + expr += "not "; + } + expr += "true"; + verifyFailedParse(expr, "ParsingFailedException: expression is too deeply nested (max 1024 levels)"); +} + +TEST_F(DocumentSelectParserTest, selection_has_upper_limit_on_input_size) { + createDocs(); + std::string expr = ("testdoctype1.a_biii" + + std::string(select::ParserLimits::MaxSelectionByteSize, 'i') + + "iiig_identifier"); + verifyFailedParse(expr, "ParsingFailedException: expression is too large to be " + "parsed (max 1048576 bytes, got 1048610)"); +} + +TEST_F(DocumentSelectParserTest, lexing_does_not_have_superlinear_time_complexity) { + createDocs(); + std::string expr = ("testdoctype1.hstringval == 'a_biii" + + std::string(select::ParserLimits::MaxSelectionByteSize - 100, 'i') + + "iiig string'"); + // If the lexer is not compiled with the appropriate options, this will take a long time. + // A really, really long time. + PARSE(expr, *_doc[0], False); +} + } // document |