summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@mongodb.com>2021-05-27 15:02:37 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-28 19:15:27 +0000
commit934d6de41bb3adbecee23e3837852e29c7ff4af6 (patch)
tree4b7f55b7668c5974ea3ef1f57237274d774df6be
parentdac40446d6c44a806e5f20b67b7ce1b6bc0a87ad (diff)
downloadmongo-934d6de41bb3adbecee23e3837852e29c7ff4af6.tar.gz
SERVER-56819 Make indexOfCP's classic engine impl always return -1 when end is less than start
-rw-r--r--jstests/aggregation/expressions/indexof_codepoints.js14
-rw-r--r--src/mongo/db/pipeline/expression.cpp6
2 files changed, 19 insertions, 1 deletions
diff --git a/jstests/aggregation/expressions/indexof_codepoints.js b/jstests/aggregation/expressions/indexof_codepoints.js
index cf885a194ec..0b729ea76a3 100644
--- a/jstests/aggregation/expressions/indexof_codepoints.js
+++ b/jstests/aggregation/expressions/indexof_codepoints.js
@@ -48,7 +48,7 @@ function testExpressionCodePoints(coll, expression, result, shouldTestEquivalenc
const coll = db.indexofcp;
coll.drop();
-assert.commandWorked(coll.insert({item: 'foobar foobar'}));
+assert.commandWorked(coll.insert({item: 'foobar foobar', emptyStr: ''}));
// Test that $indexOfCP throws an error when given a string or substring that is not a string.
assert.commandFailedWithCode(
@@ -119,6 +119,18 @@ assert.eq(null,
coll.aggregate({$project: {byteLocation: {$indexOfCP: ['$missing', '$missing']}}})
.toArray()[0]
.byteLocation);
+
+// Test the edge case of searching for an empty string inside an empty string, where the start index
+// is past the end index. These cases are designed to reproduce SERVER-56819.
+assert.eq(-1,
+ coll.aggregate({$project: {byteLocation: {$indexOfCP: ['', '$emptyStr', 3]}}})
+ .toArray()[0]
+ .byteLocation);
+assert.eq(-1,
+ coll.aggregate({$project: {byteLocation: {$indexOfCP: ['', '$emptyStr', 3, 1]}}})
+ .toArray()[0]
+ .byteLocation);
+
coll.drop();
// Test that $indexOfCP works with ASCII strings and substrings.
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp
index df977028c09..02a73e72a9e 100644
--- a/src/mongo/db/pipeline/expression.cpp
+++ b/src/mongo/db/pipeline/expression.cpp
@@ -3435,6 +3435,12 @@ Value ExpressionIndexOfCP::evaluate(const Document& root, Variables* variables)
std::min(codePointLength, static_cast<size_t>(endIndexArg.coerceToInt()));
}
+ // If the start index is past the end, then always return -1 since 'token' does not exist within
+ // these invalid bounds.
+ if (endCodePointIndex < startCodePointIndex) {
+ return Value(-1);
+ }
+
if (startByteIndex == 0 && input.empty() && token.empty()) {
// If we are finding the index of "" in the string "", the below loop will not loop, so we
// need a special case for this.