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-08-06 11:28:31 -0400
commit19ef9a7747f954baef5372367199730ca0fa643b (patch)
tree6e2d5ca3f295c5ee5092acdcea3f8b7e539b6963
parent135c6c1fa5de54a7b2e50c0163f361da90dd787e (diff)
downloadmongo-19ef9a7747f954baef5372367199730ca0fa643b.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 461f82fc736..3b0c14e6e84 100644
--- a/src/mongo/db/matcher/expression_parser.cpp
+++ b/src/mongo/db/matcher/expression_parser.cpp
@@ -427,6 +427,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 d2bcd91a1b4..73011b914c6 100644
--- a/src/mongo/db/matcher/expression_parser_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_test.cpp
@@ -285,6 +285,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());