SERVER-120668 Disallow $trim with too large mask string (#50938)
GitOrigin-RevId: 4aa52c892c56686028d2b0a48131dd620e385ac2
This commit is contained in:
parent
9a1c0b87ed
commit
c5e14f0fcf
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user