diff options
author | David Storch <david.storch@mongodb.com> | 2021-05-27 15:02:37 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-28 19:15:27 +0000 |
commit | 934d6de41bb3adbecee23e3837852e29c7ff4af6 (patch) | |
tree | 4b7f55b7668c5974ea3ef1f57237274d774df6be | |
parent | dac40446d6c44a806e5f20b67b7ce1b6bc0a87ad (diff) | |
download | mongo-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.js | 14 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 6 |
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. |