summaryrefslogtreecommitdiff
path: root/src/mongo/db/matcher
diff options
context:
space:
mode:
authorLynne Wang <lynne.wang@mongodb.com>2022-07-03 21:09:25 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-07-03 22:45:24 +0000
commit44d8e4b0819c89ae5be8fee4d10a525595158220 (patch)
tree03aae10a1429267bf5fc20859f8fcbcf50ce2e51 /src/mongo/db/matcher
parentda79de3da49f2337ec1dca076b2ac85eb246e2c0 (diff)
downloadmongo-44d8e4b0819c89ae5be8fee4d10a525595158220.tar.gz
SERVER-64002 Consistently disallow out-of-bounds access to the children vector of MatchExpressions
Diffstat (limited to 'src/mongo/db/matcher')
-rw-r--r--src/mongo/db/matcher/expression_always_boolean.h2
-rw-r--r--src/mongo/db/matcher/expression_always_boolean_test.cpp19
-rw-r--r--src/mongo/db/matcher/expression_arity.h2
-rw-r--r--src/mongo/db/matcher/expression_array.h3
-rw-r--r--src/mongo/db/matcher/expression_array_test.cpp35
-rw-r--r--src/mongo/db/matcher/expression_expr.h2
-rw-r--r--src/mongo/db/matcher/expression_expr_test.cpp12
-rw-r--r--src/mongo/db/matcher/expression_internal_bucket_geo_within.h2
-rw-r--r--src/mongo/db/matcher/expression_leaf.h2
-rw-r--r--src/mongo/db/matcher/expression_leaf_test.cpp62
-rw-r--r--src/mongo/db/matcher/expression_tree.h5
-rw-r--r--src/mongo/db/matcher/expression_tree_test.cpp69
-rw-r--r--src/mongo/db/matcher/expression_where_base.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h7
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp5
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp9
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_eq.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp12
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h7
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp7
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp10
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp10
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp10
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp10
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_object_match.h7
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp7
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp11
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h2
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp11
33 files changed, 318 insertions, 34 deletions
diff --git a/src/mongo/db/matcher/expression_always_boolean.h b/src/mongo/db/matcher/expression_always_boolean.h
index 6e0e2cdfbc8..6a97367aff5 100644
--- a/src/mongo/db/matcher/expression_always_boolean.h
+++ b/src/mongo/db/matcher/expression_always_boolean.h
@@ -79,7 +79,7 @@ public:
}
MatchExpression* getChild(size_t i) const override {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400202);
}
void resetChild(size_t, MatchExpression*) override {
diff --git a/src/mongo/db/matcher/expression_always_boolean_test.cpp b/src/mongo/db/matcher/expression_always_boolean_test.cpp
index e18c7be11e8..3290f5079a0 100644
--- a/src/mongo/db/matcher/expression_always_boolean_test.cpp
+++ b/src/mongo/db/matcher/expression_always_boolean_test.cpp
@@ -29,6 +29,7 @@
#include "mongo/platform/basic.h"
#include "mongo/db/matcher/expression_always_boolean.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -73,5 +74,23 @@ TEST(AlwaysTrueMatchExpression, EquivalentReturnsCorrectResults) {
ASSERT_FALSE(trueExpr->equivalent(&falseExpr));
}
+DEATH_TEST_REGEX(AlwaysTrueMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400202") {
+ auto trueExpr = std::make_unique<AlwaysTrueMatchExpression>();
+
+ ASSERT_EQ(trueExpr->numChildren(), 0);
+ ASSERT_THROWS_CODE(trueExpr->getChild(0), AssertionException, 6400202);
+}
+
+DEATH_TEST_REGEX(AlwaysFalseMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400202") {
+ auto falseExpr = std::make_unique<AlwaysFalseMatchExpression>();
+
+ ASSERT_EQ(falseExpr->numChildren(), 0);
+ ASSERT_THROWS_CODE(falseExpr->getChild(0), AssertionException, 6400202);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_arity.h b/src/mongo/db/matcher/expression_arity.h
index 90286200e21..a16dcf346a2 100644
--- a/src/mongo/db/matcher/expression_arity.h
+++ b/src/mongo/db/matcher/expression_arity.h
@@ -90,7 +90,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- invariant(i < nargs);
+ tassert(6400203, "Out-of-bounds access to child of MatchExpression.", i < nargs);
return _expressions[i].get();
}
diff --git a/src/mongo/db/matcher/expression_array.h b/src/mongo/db/matcher/expression_array.h
index 1b6cb5dfcc9..b1d82248c1b 100644
--- a/src/mongo/db/matcher/expression_array.h
+++ b/src/mongo/db/matcher/expression_array.h
@@ -101,6 +101,7 @@ public:
}
virtual MatchExpression* getChild(size_t i) const {
+ tassert(6400204, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
return _sub.get();
}
@@ -168,6 +169,7 @@ public:
}
virtual MatchExpression* getChild(size_t i) const {
+ tassert(6400205, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
return _subs[i].get();
}
@@ -215,6 +217,7 @@ public:
}
MatchExpression* getChild(size_t i) const override {
+ tassert(6400206, "SizeMatchExpression does not have any children.", i < numChildren());
return nullptr;
}
diff --git a/src/mongo/db/matcher/expression_array_test.cpp b/src/mongo/db/matcher/expression_array_test.cpp
index e1dea305466..7d9cbd6ef93 100644
--- a/src/mongo/db/matcher/expression_array_test.cpp
+++ b/src/mongo/db/matcher/expression_array_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_tree.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -153,6 +154,18 @@ TEST(ElemMatchObjectMatchExpression, Collation) {
ASSERT(op.matchesSingleElement(notMatch["a"]));
}
+DEATH_TEST_REGEX(ElemMatchObjectMatchExpression,
+ GetChildFailsIndexGreaterThanOne,
+ "Tripwire assertion.*6400204") {
+ auto baseOperand = BSON("c" << 6);
+ auto eq = std::make_unique<EqualityMatchExpression>("c", baseOperand["c"]);
+ auto op = ElemMatchObjectMatchExpression{"a.b", std::move(eq)};
+
+ const size_t numChildren = 1;
+ ASSERT_EQ(op.numChildren(), numChildren);
+ ASSERT_THROWS_CODE(op.getChild(numChildren), AssertionException, 6400204);
+}
+
/**
TEST(ElemMatchObjectMatchExpression, MatchesIndexKey) {
auto baseOperand = BSON("b" << 5);
@@ -245,6 +258,18 @@ TEST(ElemMatchValueMatchExpression, ElemMatchKey) {
ASSERT_EQUALS("2", details.elemMatchKey());
}
+DEATH_TEST_REGEX(ElemMatchValueMatchExpression,
+ GetChildFailsOnIndexLargerThanChildSet,
+ "Tripwire assertion.*6400205") {
+ auto baseOperand = BSON("$gt" << 6);
+ auto gt = std::make_unique<GTMatchExpression>("", baseOperand["$gt"]);
+ auto op = ElemMatchValueMatchExpression{"a.b", std::unique_ptr<MatchExpression>{std::move(gt)}};
+
+ const size_t numChildren = 1;
+ ASSERT_EQ(op.numChildren(), numChildren);
+ ASSERT_THROWS_CODE(op.getChild(numChildren), AssertionException, 6400205);
+}
+
/**
TEST(ElemMatchValueMatchExpression, MatchesIndexKey) {
auto baseOperand = BSON("$lt" << 5);
@@ -410,6 +435,16 @@ TEST(SizeMatchExpression, Equivalent) {
ASSERT(!e1.equivalent(&e3));
}
+DEATH_TEST_REGEX(SizeMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400206") {
+ auto e1 = SizeMatchExpression{"a", 5};
+
+ const size_t numChildren = 0;
+ ASSERT_EQ(e1.numChildren(), numChildren);
+ ASSERT_THROWS_CODE(e1.getChild(0), AssertionException, 6400206);
+}
+
/**
TEST(SizeMatchExpression, MatchesIndexKey) {
auto operand = BSON("$size" << 4);
diff --git a/src/mongo/db/matcher/expression_expr.h b/src/mongo/db/matcher/expression_expr.h
index 281fdd3afd6..0d1110f5bac 100644
--- a/src/mongo/db/matcher/expression_expr.h
+++ b/src/mongo/db/matcher/expression_expr.h
@@ -88,7 +88,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400207);
}
void resetChild(size_t, MatchExpression*) {
diff --git a/src/mongo/db/matcher/expression_expr_test.cpp b/src/mongo/db/matcher/expression_expr_test.cpp
index 5ff0cbf88e9..801b3634813 100644
--- a/src/mongo/db/matcher/expression_expr_test.cpp
+++ b/src/mongo/db/matcher/expression_expr_test.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -735,5 +736,16 @@ TEST_F(ExprMatchTest, ExpressionEvaluationReturnsResultsCorrectly) {
ASSERT_EQUALS(-2, expressionResult.coerceToInt());
}
+DEATH_TEST_REGEX(ExprMatchTest, GetChildFailsIndexGreaterThanZero, "Tripwire assertion.*6400207") {
+ BSONObj exprBson = fromjson("{$expr: {$and: [{$eq: ['$a', 1]}, {$eq: ['$b', 2]}]}}");
+
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matchExpr =
+ std::make_unique<ExprMatchExpression>(exprBson.firstElement(), std::move(expCtx));
+
+ ASSERT_EQ(matchExpr->numChildren(), 0);
+ ASSERT_THROWS_CODE(matchExpr->getChild(0), AssertionException, 6400207);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_internal_bucket_geo_within.h b/src/mongo/db/matcher/expression_internal_bucket_geo_within.h
index 34ec2ad9211..2395cf97c16 100644
--- a/src/mongo/db/matcher/expression_internal_bucket_geo_within.h
+++ b/src/mongo/db/matcher/expression_internal_bucket_geo_within.h
@@ -107,7 +107,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400208);
}
void resetChild(size_t, MatchExpression*) {
diff --git a/src/mongo/db/matcher/expression_leaf.h b/src/mongo/db/matcher/expression_leaf.h
index 14fceae1f5f..bd6bc577672 100644
--- a/src/mongo/db/matcher/expression_leaf.h
+++ b/src/mongo/db/matcher/expression_leaf.h
@@ -101,7 +101,7 @@ public:
}
MatchExpression* getChild(size_t i) const override {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400209);
}
diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp
index 99bedfa067f..450e71d0367 100644
--- a/src/mongo/db/matcher/expression_leaf_test.cpp
+++ b/src/mongo/db/matcher/expression_leaf_test.cpp
@@ -2198,4 +2198,66 @@ TEST(MatchesBSONElement, ArrayEquality) {
ASSERT_FALSE(filter.matchesBSON(iObjArr));
}
+DEATH_TEST_REGEX(RegexMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400209") {
+ BSONObj match = BSON("a"
+ << "b");
+ BSONObj notMatch = BSON("a"
+ << "c");
+ RegexMatchExpression regex("", "b", "");
+
+ ASSERT_EQ(regex.numChildren(), 0);
+ ASSERT_THROWS_CODE(regex.getChild(0), AssertionException, 6400209);
+}
+
+DEATH_TEST_REGEX(ModMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400209") {
+ ModMatchExpression mod("a", 5, 2);
+
+ ASSERT_EQ(mod.numChildren(), 0);
+ ASSERT_THROWS_CODE(mod.getChild(0), AssertionException, 6400209);
+}
+
+DEATH_TEST_REGEX(ExistsMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400209") {
+ ExistsMatchExpression exists("a");
+
+ ASSERT_EQ(exists.numChildren(), 0);
+ ASSERT_THROWS_CODE(exists.getChild(0), AssertionException, 6400209);
+}
+
+DEATH_TEST_REGEX(InMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400209") {
+ InMatchExpression in("a");
+
+ ASSERT_EQ(in.numChildren(), 0);
+ ASSERT_THROWS_CODE(in.getChild(0), AssertionException, 6400209);
+}
+
+DEATH_TEST_REGEX(BitTestMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400209") {
+ long long bitMask = 54;
+
+ BitsAllSetMatchExpression balls("a", bitMask);
+
+ ASSERT_EQ(balls.numChildren(), 0);
+ ASSERT_THROWS_CODE(balls.getChild(0), AssertionException, 6400209);
+}
+
+DEATH_TEST_REGEX(ComparisonMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400209") {
+ BSONObj operand = BSON("a"
+ << "string");
+ EqualityMatchExpression eq("a", operand["a"]);
+
+ ASSERT_EQ(eq.numChildren(), 0);
+ ASSERT_THROWS_CODE(eq.getChild(0), AssertionException, 6400209);
+}
+
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_tree.h b/src/mongo/db/matcher/expression_tree.h
index f8b9179c003..f5ab4bb5a8e 100644
--- a/src/mongo/db/matcher/expression_tree.h
+++ b/src/mongo/db/matcher/expression_tree.h
@@ -61,6 +61,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
+ tassert(6400201, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
return _expressions[i].get();
}
@@ -238,6 +239,7 @@ public:
class NotMatchExpression final : public MatchExpression {
public:
+ static constexpr int kNumChildren = 1;
explicit NotMatchExpression(MatchExpression* e,
clonable_ptr<ErrorAnnotation> annotation = nullptr)
: MatchExpression(NOT, std::move(annotation)), _exp(e) {}
@@ -270,10 +272,11 @@ public:
bool equivalent(const MatchExpression* other) const final;
size_t numChildren() const final {
- return 1;
+ return kNumChildren;
}
MatchExpression* getChild(size_t i) const final {
+ tassert(6400210, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
return _exp.get();
}
diff --git a/src/mongo/db/matcher/expression_tree_test.cpp b/src/mongo/db/matcher/expression_tree_test.cpp
index 16c03b31336..562f6aad673 100644
--- a/src/mongo/db/matcher/expression_tree_test.cpp
+++ b/src/mongo/db/matcher/expression_tree_test.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_tree.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
+#include "mongo/unittest/death_test.h"
namespace mongo {
@@ -85,6 +86,17 @@ TEST(NotMatchExpression, SetCollatorPropagatesToChild) {
nullptr));
}
+DEATH_TEST_REGEX(NotMatchExpression,
+ GetChildFailsIndexLargerThanOne,
+ "Tripwire assertion.*6400210") {
+ auto baseOperand = BSON("$lt" << 5);
+ auto lt = std::make_unique<LTMatchExpression>("a", baseOperand["$lt"]);
+ auto notOp = NotMatchExpression{lt.release()};
+
+ ASSERT_EQ(notOp.numChildren(), 1);
+ ASSERT_THROWS_CODE(notOp.getChild(1), AssertionException, 6400210);
+}
+
TEST(AndOp, NoClauses) {
auto andMatchExpression = AndMatchExpression{};
ASSERT(andMatchExpression.matchesBSON(BSONObj{}, nullptr));
@@ -177,6 +189,25 @@ TEST(AndOp, ElemMatchKey) {
ASSERT_EQUALS("1", details.elemMatchKey());
}
+DEATH_TEST_REGEX(AndOp, GetChildFailsOnIndexLargerThanChildren, "Tripwire assertion.*6400201") {
+ auto baseOperand1 = BSON("$gt" << 1);
+ auto baseOperand2 = BSON("$lt" << 10);
+ auto baseOperand3 = BSON("$lt" << 100);
+
+ auto sub1 = std::make_unique<GTMatchExpression>("a", baseOperand1["$gt"]);
+ auto sub2 = std::make_unique<LTMatchExpression>("a", baseOperand2["$lt"]);
+ auto sub3 = std::make_unique<LTMatchExpression>("b", baseOperand3["$lt"]);
+
+ auto andOp = AndMatchExpression{};
+ andOp.add(std::move(sub1));
+ andOp.add(std::move(sub2));
+ andOp.add(std::move(sub3));
+
+ const size_t numChildren = 3;
+ ASSERT_EQ(andOp.numChildren(), numChildren);
+ ASSERT_THROWS_CODE(andOp.getChild(numChildren), AssertionException, 6400201);
+}
+
TEST(OrOp, NoClauses) {
auto orOp = OrMatchExpression{};
ASSERT(!orOp.matchesBSON(BSONObj{}, nullptr));
@@ -270,6 +301,24 @@ TEST(OrOp, ElemMatchKey) {
ASSERT(!details.hasElemMatchKey());
}
+DEATH_TEST_REGEX(OrOp, GetChildFailsOnIndexLargerThanChildren, "Tripwire assertion.*6400201") {
+ auto baseOperand1 = BSON("$gt" << 10);
+ auto baseOperand2 = BSON("$lt" << 0);
+ auto baseOperand3 = BSON("b" << 100);
+ auto sub1 = std::make_unique<GTMatchExpression>("a", baseOperand1["$gt"]);
+ auto sub2 = std::make_unique<LTMatchExpression>("a", baseOperand2["$lt"]);
+ auto sub3 = std::make_unique<EqualityMatchExpression>("b", baseOperand3["b"]);
+
+ auto orOp = OrMatchExpression{};
+ orOp.add(std::move(sub1));
+ orOp.add(std::move(sub2));
+ orOp.add(std::move(sub3));
+
+ const size_t numChildren = 3;
+ ASSERT_EQ(orOp.numChildren(), numChildren);
+ ASSERT_THROWS_CODE(orOp.getChild(numChildren), AssertionException, 6400201);
+}
+
TEST(NorOp, NoClauses) {
auto norOp = NorMatchExpression{};
ASSERT(norOp.matchesBSON(BSONObj{}, nullptr));
@@ -350,4 +399,24 @@ TEST(NorOp, Equivalent) {
ASSERT(e1.equivalent(&e1));
ASSERT(!e1.equivalent(&e2));
}
+
+DEATH_TEST_REGEX(NorOp, GetChildFailsOnIndexLargerThanChildren, "Tripwire assertion.*6400201") {
+ auto baseOperand1 = BSON("$gt" << 10);
+ auto baseOperand2 = BSON("$lt" << 0);
+ auto baseOperand3 = BSON("b" << 100);
+
+ auto sub1 = std::make_unique<GTMatchExpression>("a", baseOperand1["$gt"]);
+ auto sub2 = std::make_unique<LTMatchExpression>("a", baseOperand2["$lt"]);
+ auto sub3 = std::make_unique<EqualityMatchExpression>("b", baseOperand3["b"]);
+
+ auto norOp = NorMatchExpression{};
+ norOp.add(std::move(sub1));
+ norOp.add(std::move(sub2));
+ norOp.add(std::move(sub3));
+
+ const size_t numChildren = 3;
+ ASSERT_EQ(norOp.numChildren(), numChildren);
+ ASSERT_THROWS_CODE(norOp.getChild(numChildren), AssertionException, 6400201);
+}
+
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_where_base.h b/src/mongo/db/matcher/expression_where_base.h
index 550e94d1d37..3f5099d7180 100644
--- a/src/mongo/db/matcher/expression_where_base.h
+++ b/src/mongo/db/matcher/expression_where_base.h
@@ -51,7 +51,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400211);
}
void resetChild(size_t, MatchExpression*) {
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h
index 0a613b23303..8d830f916b9 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h
@@ -45,6 +45,7 @@ class InternalSchemaAllElemMatchFromIndexMatchExpression final
: public ArrayMatchingMatchExpression {
public:
static constexpr StringData kName = "$_internalSchemaAllElemMatchFromIndex"_sd;
+ static constexpr int kNumChildren = 1;
InternalSchemaAllElemMatchFromIndexMatchExpression(
StringData path,
@@ -93,16 +94,16 @@ public:
}
size_t numChildren() const final {
- return 1;
+ return kNumChildren;
}
MatchExpression* getChild(size_t i) const final {
- invariant(i == 0);
+ tassert(6400200, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
return _expression->getFilter();
}
void resetChild(size_t i, MatchExpression* other) {
- tassert(6329407, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
+ tassert(6329407, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
_expression->resetFilter(other);
};
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp
index 49e1b3b0235..dd1be3e030f 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp
@@ -127,13 +127,14 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FindsFirstMismatchInArr
DEATH_TEST_REGEX(InternalSchemaAllElemMatchFromIndexMatchExpression,
GetChildFailsIndexGreaterThanOne,
- "Invariant failure.*i == 0") {
+ "Tripwire assertion.*6400200") {
auto query = fromjson("{'a.b': {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
- objMatch.getValue()->getChild(1);
+ ASSERT_EQ(objMatch.getValue()->numChildren(), 1);
+ ASSERT_THROWS_CODE(objMatch.getValue()->getChild(1), AssertionException, 6400200);
}
} // namespace
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h
index 08e1a1affc6..a55c268bee7 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h
@@ -149,7 +149,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- invariant(i < numChildren());
+ tassert(6400212, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
if (i == 0) {
return _otherwise->getFilter();
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp
index 399d8917001..b14a1b8adca 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp
@@ -135,9 +135,9 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, HasCorrectNumberOfChilden)
ASSERT(objMatch.getValue()->getChild(0));
}
-DEATH_TEST(InternalSchemaAllowedPropertiesMatchExpression,
- GetChildFailsOnIndexLargerThanChildSet,
- "i < numChildren()") {
+DEATH_TEST_REGEX(InternalSchemaAllowedPropertiesMatchExpression,
+ GetChildFailsOnIndexLargerThanChildSet,
+ "Tripwire assertion.*6400212") {
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a'], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, expression: {i: 1}}], otherwise: {i: 7}}}");
@@ -146,6 +146,7 @@ DEATH_TEST(InternalSchemaAllowedPropertiesMatchExpression,
ASSERT_OK(objMatch.getStatus());
const size_t numChildren = 2;
- objMatch.getValue()->getChild(numChildren);
+ ASSERT_EQ(objMatch.getValue()->numChildren(), numChildren);
+ ASSERT_THROWS_CODE(objMatch.getValue()->getChild(numChildren), AssertionException, 6400212);
}
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_eq.h b/src/mongo/db/matcher/schema/expression_internal_schema_eq.h
index 3f604294f60..30882ca6c21 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_eq.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_eq.h
@@ -68,7 +68,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400213);
}
void resetChild(size_t, MatchExpression*) override {
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp
index 8be245c1fbc..25cacca243e 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/matcher/schema/expression_internal_schema_eq.h"
#include "mongo/db/pipeline/expression_context_for_test.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -137,5 +138,16 @@ TEST(InternalSchemaEqMatchExpression, EquivalentToClone) {
auto clone = rootDocEq.getMatchExpression()->shallowClone();
ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(clone.get()));
}
+
+DEATH_TEST_REGEX(InternalSchemaEqMatchExpression,
+ GetChildFailsLargerThanZero,
+ "Tripwire assertion.*6400213") {
+ BSONObj operand = BSON("a" << 5);
+ InternalSchemaEqMatchExpression eq("a", operand["a"]);
+
+ ASSERT_EQ(eq.numChildren(), 0);
+ ASSERT_THROWS_CODE(eq.getChild(0), AssertionException, 6400213);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h
index 8fff1225bf3..3f30356b6aa 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h
@@ -43,6 +43,7 @@ namespace mongo {
class InternalSchemaMatchArrayIndexMatchExpression final : public ArrayMatchingMatchExpression {
public:
static constexpr StringData kName = "$_internalSchemaMatchArrayIndex"_sd;
+ static constexpr int kNumChildren = 1;
InternalSchemaMatchArrayIndexMatchExpression(
StringData path,
@@ -82,16 +83,16 @@ public:
}
size_t numChildren() const final {
- return 1;
+ return kNumChildren;
}
MatchExpression* getChild(size_t i) const final {
- invariant(i == 0);
+ tassert(6400214, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
return _expression->getFilter();
}
void resetChild(size_t i, MatchExpression* other) final override {
- tassert(6329409, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
+ tassert(6329409, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
_expression->resetFilter(other);
}
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp
index 854c2cf73a8..b6308f7ca0a 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp
@@ -129,8 +129,8 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, HasSingleChild) {
}
DEATH_TEST_REGEX(InternalSchemaMatchArrayIndexMatchExpression,
- GetChildFailsIndexGreaterThanZero,
- "Invariant failure.*i == 0") {
+ GetChildFailsIndexGreaterThanOne,
+ "Tripwire assertion.*6400214") {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$type: 'number'}}}}}");
@@ -138,7 +138,8 @@ DEATH_TEST_REGEX(InternalSchemaMatchArrayIndexMatchExpression,
auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
- objMatch.getValue()->getChild(1);
+ ASSERT_EQ(objMatch.getValue()->numChildren(), 1);
+ ASSERT_THROWS_CODE(objMatch.getValue()->getChild(1), AssertionException, 6400214);
}
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp
index 0ce7df4d579..9e498591631 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/schema/expression_internal_schema_max_items.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -86,5 +87,14 @@ TEST(InternalSchemaMaxItemsMatchExpression, NestedArraysWorkWithDottedPaths) {
ASSERT(!maxItems.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1 << 2 << 3)))));
}
+DEATH_TEST_REGEX(InternalSchemaMaxItemsMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400215") {
+ InternalSchemaMaxItemsMatchExpression maxItems("a", 2);
+
+ ASSERT_EQ(maxItems.numChildren(), 0);
+ ASSERT_THROWS_CODE(maxItems.getChild(0), AssertionException, 6400215);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp
index 6c8327e9017..587243cb0ad 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/schema/expression_internal_schema_max_properties.h"
#include "mongo/db/matcher/schema/expression_internal_schema_min_properties.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -89,5 +90,14 @@ TEST(InternalSchemaMaxPropertiesMatchExpression, MinPropertiesNotEquivalentToMax
ASSERT_FALSE(maxProperties.equivalent(&minProperties));
}
+DEATH_TEST_REGEX(InternalSchemaMaxPropertiesMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400216") {
+ InternalSchemaMaxPropertiesMatchExpression maxProperties(5);
+
+ ASSERT_EQ(maxProperties.numChildren(), 0);
+ ASSERT_THROWS_CODE(maxProperties.getChild(0), AssertionException, 6400216);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp
index 7cb5af3547f..989e4ba8a0c 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/schema/expression_internal_schema_min_items.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -85,5 +86,14 @@ TEST(InternalSchemaMinItemsMatchExpression, NestedArraysWorkWithDottedPaths) {
ASSERT(!minItems.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1)))));
}
+DEATH_TEST_REGEX(InternalSchemaMinItemsMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400215") {
+ InternalSchemaMinItemsMatchExpression minItems("a", 2);
+
+ ASSERT_EQ(minItems.numChildren(), 0);
+ ASSERT_THROWS_CODE(minItems.getChild(0), AssertionException, 6400215);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp
index 8703940f525..c7abaa0c4e1 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/schema/expression_internal_schema_max_properties.h"
#include "mongo/db/matcher/schema/expression_internal_schema_min_properties.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -81,5 +82,14 @@ TEST(InternalSchemaMinPropertiesMatchExpression, EquivalentFunctionIsAccurate) {
ASSERT_FALSE(minProperties1.equivalent(&minProperties3));
}
+DEATH_TEST_REGEX(InternalSchemaMinPropertiesMatchExpression,
+ GetChildFailsIndexGreaterThanZero,
+ "Tripwire assertion.*6400216") {
+ InternalSchemaMaxPropertiesMatchExpression minProperties(1);
+
+ ASSERT_EQ(minProperties.numChildren(), 0);
+ ASSERT_THROWS_CODE(minProperties.getChild(0), AssertionException, 6400216);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h
index 99ed79ec5d6..5ecf216dd60 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h
@@ -61,7 +61,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400215);
}
void resetChild(size_t i, MatchExpression* other) override {
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h b/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h
index 29fd4fc6145..11c6be03aca 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h
@@ -58,7 +58,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400216);
}
void resetChild(size_t, MatchExpression*) override {
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h b/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h
index 93b6e1b765e..6b18cd2fb46 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h
@@ -38,6 +38,7 @@ namespace mongo {
class InternalSchemaObjectMatchExpression final : public PathMatchExpression {
public:
static constexpr StringData kName = "$_internalSchemaObjectMatch"_sd;
+ static constexpr int kNumChildren = 1;
InternalSchemaObjectMatchExpression(StringData path,
std::unique_ptr<MatchExpression> expr,
@@ -59,17 +60,17 @@ public:
size_t numChildren() const final {
invariant(_sub);
- return 1;
+ return kNumChildren;
}
MatchExpression* getChild(size_t i) const final {
// 'i' must be 0 since there's always exactly one child.
- invariant(i == 0);
+ tassert(6400217, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
return _sub.get();
}
void resetChild(size_t i, MatchExpression* other) final override {
- tassert(6329410, "Out-of-bounds access to child of MatchExpression.", i < numChildren());
+ tassert(6329410, "Out-of-bounds access to child of MatchExpression.", i < kNumChildren);
_sub.reset(other);
}
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp
index f161bbd5eb2..e3b67bd4828 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp
@@ -218,8 +218,8 @@ TEST(InternalSchemaObjectMatchExpression, HasSingleChild) {
}
DEATH_TEST_REGEX(InternalSchemaObjectMatchExpression,
- GetChildFailsIndexGreaterThanZero,
- "Invariant failure.*i == 0") {
+ GetChildFailsIndexGreaterThanOne,
+ "Tripwire assertion.*6400217") {
auto query = fromjson(
" {a: {$_internalSchemaObjectMatch: {"
" c: {$eq: 3}"
@@ -228,7 +228,8 @@ DEATH_TEST_REGEX(InternalSchemaObjectMatchExpression,
auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
- objMatch.getValue()->getChild(1);
+ ASSERT_EQ(objMatch.getValue()->numChildren(), 1);
+ ASSERT_THROWS_CODE(objMatch.getValue()->getChild(1), AssertionException, 6400217);
}
} // namespace
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h
index 62dfb6d66a2..ba422253bf2 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h
@@ -81,7 +81,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400218);
}
void resetChild(size_t i, MatchExpression*) final override {
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp
index fe628c66f2b..596db5a95eb 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h"
#include "mongo/db/pipeline/expression_context_for_test.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -113,5 +114,15 @@ TEST(InternalSchemaRootDocEqMatchExpression, EquivalentToClone) {
auto clone = rootDocEq.getMatchExpression()->shallowClone();
ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(clone.get()));
}
+
+DEATH_TEST_REGEX(InternalSchemaRootDocEqMatchExpression,
+ GetChildFailsIndexLargerThanZero,
+ "Tripwire assertion.*6400218") {
+ InternalSchemaRootDocEqMatchExpression rootDocEq(BSON("a" << 1 << "b" << BSON("c" << 1)));
+
+ ASSERT_EQ(rootDocEq.numChildren(), 0);
+ ASSERT_THROWS_CODE(rootDocEq.getChild(0), AssertionException, 6400218);
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h
index ddb86c89403..9693ba681e7 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h
@@ -57,7 +57,7 @@ public:
}
MatchExpression* getChild(size_t i) const final {
- MONGO_UNREACHABLE;
+ MONGO_UNREACHABLE_TASSERT(6400219);
}
void resetChild(size_t i, MatchExpression*) final override {
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp
index 7215499b78b..70d0491a947 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp
@@ -32,6 +32,7 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/schema/expression_internal_schema_unique_items.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -115,5 +116,15 @@ TEST(InternalSchemaUniqueItemsMatchExpression, FindsFirstDuplicateValue) {
ASSERT_FALSE(uniqueItems.findFirstDuplicateValue(fromjson("[1, 2]}")));
ASSERT_FALSE(uniqueItems.findFirstDuplicateValue(fromjson("[]}")));
}
+
+DEATH_TEST_REGEX(InternalSchemaUniqueItemsMatchExpression,
+ GetChildFailsIndexLargerThanZero,
+ "Tripwire assertion.*6400219") {
+ InternalSchemaUniqueItemsMatchExpression uniqueItems("foo");
+
+ ASSERT_EQ(uniqueItems.numChildren(), 0);
+ ASSERT_THROWS_CODE(uniqueItems.getChild(0), AssertionException, 6400219);
+}
+
} // namespace
} // namespace mongo