diff options
author | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2018-07-20 16:35:44 -0400 |
---|---|---|
committer | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2018-07-30 11:28:06 -0400 |
commit | b855ed29f63bec4ce7b2a5364647fb3657778b47 (patch) | |
tree | 57fc318ff0b48d2e778d26279af8bca77a7e2ebe | |
parent | f33bcaa9812a0590d06a70ecb7778e5e40396fe6 (diff) | |
download | mongo-b855ed29f63bec4ce7b2a5364647fb3657778b47.tar.gz |
SERVER-36239: MatchExpression parser should reject a $text query that is not operating on the top level document
(cherry picked from commit fbd991a76e141a2744b18f3f9954f345136bba6b)
-rw-r--r-- | src/mongo/db/matcher/expression_parser.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/matcher/expression_parser_test.cpp | 24 |
2 files changed, 29 insertions, 0 deletions
diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp index 10b089d0081..18d13f5c20f 100644 --- a/src/mongo/db/matcher/expression_parser.cpp +++ b/src/mongo/db/matcher/expression_parser.cpp @@ -455,6 +455,11 @@ StatusWithMatchExpression parseText(StringData name, const ExtensionsCallback* extensionsCallback, MatchExpressionParser::AllowedFeatureSet allowedFeatures, DocumentParseLevel currentLevel) { + if (currentLevel == DocumentParseLevel::kUserSubDocument) { + return { + Status(ErrorCodes::BadValue, "$text can only be applied to the top-level document")}; + } + if ((allowedFeatures & MatchExpressionParser::AllowedFeatures::kText) == 0u) { return {Status(ErrorCodes::BadValue, "$text is not allowed in this context")}; } diff --git a/src/mongo/db/matcher/expression_parser_test.cpp b/src/mongo/db/matcher/expression_parser_test.cpp index 4343cf60403..6a78d7b7cc4 100644 --- a/src/mongo/db/matcher/expression_parser_test.cpp +++ b/src/mongo/db/matcher/expression_parser_test.cpp @@ -335,6 +335,30 @@ TEST(MatchExpressionParserTest, TextParsesSuccessfullyWhenAllowed) { .getStatus()); } +TEST(MatchExpressionParserTest, TextFailsToParseIfNotTopLevel) { + auto query = fromjson("{a: {$text: {$search: 'str'}}}"); + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + ASSERT_NOT_OK( + MatchExpressionParser::parse( + query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::AllowedFeatures::kText) + .getStatus()); +} + +TEST(MatchExpressionParserTest, TextWithinElemMatchFailsToParse) { + auto query = fromjson("{a: {$elemMatch: {$text: {$search: 'str'}}}}"); + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + ASSERT_NOT_OK( + MatchExpressionParser::parse( + query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::AllowedFeatures::kText) + .getStatus()); + + query = fromjson("{a: {$elemMatch: {$elemMatch: {$text: {$search: 'str'}}}}}"); + ASSERT_NOT_OK( + MatchExpressionParser::parse( + query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::AllowedFeatures::kText) + .getStatus()); +} + TEST(MatchExpressionParserTest, WhereFailsToParseWhenDisallowed) { auto query = fromjson("{$where: 'this.a == this.b'}"); boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); |