summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Zolnierz <nicholas.zolnierz@mongodb.com>2018-07-20 16:35:44 -0400
committerNick Zolnierz <nicholas.zolnierz@mongodb.com>2018-07-30 11:28:06 -0400
commitb855ed29f63bec4ce7b2a5364647fb3657778b47 (patch)
tree57fc318ff0b48d2e778d26279af8bca77a7e2ebe
parentf33bcaa9812a0590d06a70ecb7778e5e40396fe6 (diff)
downloadmongo-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.cpp5
-rw-r--r--src/mongo/db/matcher/expression_parser_test.cpp24
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());