SERVER-120668 Disallow $trim with too large mask string (#50938)

GitOrigin-RevId: 4aa52c892c56686028d2b0a48131dd620e385ac2
This commit is contained in:
Rui Liu 2026-04-03 10:17:22 +02:00 committed by MongoDB Bot
parent 9a1c0b87ed
commit c5e14f0fcf
6 changed files with 38 additions and 4 deletions

View File

@ -528,6 +528,8 @@ last-continuous:
ticket: SERVER-112273
- test_file: jstests/replsets/election_term_over_int_max.js
ticket: SERVER-119413
- test_file: jstests/aggregation/expressions/trim.js
ticket: SERVER-120668
suites: null
last-lts:
all:
@ -1113,4 +1115,6 @@ last-lts:
ticket: SERVER-112273
- test_file: jstests/replsets/election_term_over_int_max.js
ticket: SERVER-119413
- test_file: jstests/aggregation/expressions/trim.js
ticket: SERVER-120668
suites: null

View File

@ -167,3 +167,12 @@ for (const op of ["$trim", "$ltrim", "$rtrim"]) {
assertErrorCode(coll, [{$project: {x: {[op]: {input: "$_id"}}}}], 50699);
assertErrorCode(coll, [{$project: {x: {[op]: {input: "$nonObject", chars: "$_id"}}}}], 50700);
}
assert(coll.drop());
assert.commandWorked(coll.insert([{_id: 0, str: " x "}]));
// Test that characters limit is triggered correctly (for all of $trim, $ltrim, $rtrim).
for (const op of ["$trim", "$ltrim", "$rtrim"]) {
assertErrorCode(
coll, [{$project: {x: {[op]: {input: "$str", chars: " ".repeat(4097)}}}}], 12066800);
}

View File

@ -211,6 +211,7 @@ const equivalentErrorCodesList = [
[5787903, 8178107, 8070607, 8155711],
[5787902, 8178113, 8070609, 8070610, 8155720],
[5787908, 8178108, 8070608, 8155708],
[12066800, 12066801],
];
// This map is generated based on the contents of 'equivalentErrorCodesList'. This map should _not_

View File

@ -276,9 +276,17 @@ Value evaluate(const ExpressionTrim& expr, const Document& root, Variables* vari
<< typeName(unvalidatedUserChars.getType()) << ") instead.",
unvalidatedUserChars.getType() == BSONType::string);
auto unvalidatedUserCharsStringData = unvalidatedUserChars.getStringData();
uassert(12066800,
str::stream() << expr.getName() << " requires 'chars' to be not greater than "
<< str_trim_utils::kMaximumAllowedTrimStringBytes << " bytes, got "
<< unvalidatedUserCharsStringData.length() << " bytes instead.",
unvalidatedUserCharsStringData.length() <=
str_trim_utils::kMaximumAllowedTrimStringBytes);
return Value(str_trim_utils::doTrim(
input,
str_trim_utils::extractCodePointsFromChars(unvalidatedUserChars.getStringData()),
str_trim_utils::extractCodePointsFromChars(unvalidatedUserCharsStringData),
trimType == ExpressionTrim::TrimType::kBoth || trimType == ExpressionTrim::TrimType::kLeft,
trimType == ExpressionTrim::TrimType::kBoth ||
trimType == ExpressionTrim::TrimType::kRight));

View File

@ -326,11 +326,21 @@ FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTrim(ArityType a
return {false, value::TypeTags::Nothing, 0};
}
std::vector<StringData> replacementChars;
// Nullish 'chars' indicates that it was not provided and the default whitespace characters will
// be used.
auto replacementChars = !value::isNullish(tagChars)
? str_trim_utils::extractCodePointsFromChars(value::getStringView(tagChars, valChars))
: str_trim_utils::kDefaultTrimWhitespaceChars;
if (value::isNullish(tagChars)) {
replacementChars = str_trim_utils::kDefaultTrimWhitespaceChars;
} else {
auto charsStringData = value::getStringView(tagChars, valChars);
uassert(12066801,
str::stream() << "$trim/$ltrim/$rtrim requires 'chars' to be not greater than "
<< str_trim_utils::kMaximumAllowedTrimStringBytes << " bytes, got "
<< charsStringData.length() << " bytes instead.",
charsStringData.length() <= str_trim_utils::kMaximumAllowedTrimStringBytes);
replacementChars = str_trim_utils::extractCodePointsFromChars(charsStringData);
}
auto inputString = value::getStringView(tagInput, valInput);
auto [strTag, strValue] = sbe::value::makeNewString(

View File

@ -39,6 +39,8 @@
namespace mongo::str_trim_utils {
const size_t kMaximumAllowedTrimStringBytes = 4096;
const std::vector<StringData> kDefaultTrimWhitespaceChars = {
"\0"_sd, // Null character. Avoid using "\u0000" syntax to work around a gcc bug:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53690.