summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlya Berciu <alya.berciu@mongodb.com>2023-04-12 13:13:04 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-04-12 13:57:33 +0000
commitfeca2cd33e6d317374363f008a214aebabce6a52 (patch)
tree582a5090a7d4df651a494abb679c8e6b7fe31606
parent46832492a977b636552649f00cfdb9e2c242cebf (diff)
downloadmongo-feca2cd33e6d317374363f008a214aebabce6a52.tar.gz
SERVER-75517 Add additional dollar-prefix validation in _id
-rw-r--r--etc/backports_required_for_multiversion_tests.yml4
-rw-r--r--jstests/core/field_name_validation.js10
-rw-r--r--src/mongo/db/update/storage_validation.cpp33
3 files changed, 36 insertions, 11 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml
index 1f45533046e..56e36f3cc87 100644
--- a/etc/backports_required_for_multiversion_tests.yml
+++ b/etc/backports_required_for_multiversion_tests.yml
@@ -326,6 +326,8 @@ last-continuous:
ticket: SERVER-74460
- test_file: jstests/sharding/query/group_plan_cache_sharded.js
ticket: SERVER-74245
+ - test_file: jstests/core/field_name_validation.js
+ ticket: SERVER-75517
suites: null
last-lts:
all:
@@ -715,4 +717,6 @@ last-lts:
ticket: SERVER-73938
- test_file: jstests/sharding/shard_keys_with_dollar_sign.js
ticket: SERVER-74124
+ - test_file: jstests/core/field_name_validation.js
+ ticket: SERVER-75517
suites: null
diff --git a/jstests/core/field_name_validation.js b/jstests/core/field_name_validation.js
index 7dd249f98b2..42d0d5cf21d 100644
--- a/jstests/core/field_name_validation.js
+++ b/jstests/core/field_name_validation.js
@@ -66,6 +66,9 @@ assert.commandWorked(coll.insert({_id: 2, $valid: 1, $db: 1}));
assert.commandWorked(coll.insert({_id: 3, $valid: 1, $ref: 1}));
assert.commandWorked(coll.insert({_id: 4, $valid: 1, $alsoValid: 1}));
+// Valid, because _id.$gt is a field name, and not equivalent to {_id: {$gt: 4}}
+assert.commandWorked(coll.insert({"_id.$gt": 4}));
+
//
// Update command field name validation.
//
@@ -93,9 +96,16 @@ assert.writeErrorWithCode(coll.update({"a.b": 1}, {_id: {$invalid: 1}}, {upsert:
ErrorCodes.DollarPrefixedFieldName);
assert.writeErrorWithCode(coll.update({"a.b": 1}, {$set: {_id: {$invalid: 1}}}, {upsert: true}),
ErrorCodes.DollarPrefixedFieldName);
+assert.writeErrorWithCode(coll.update({"a.b": 1}, {$set: {"_id.$gt": 1}}, {upsert: true}),
+ ErrorCodes.DollarPrefixedFieldName);
assert.writeErrorWithCode(
coll.update({"a.b": 1}, {$setOnInsert: {_id: {$invalid: 1}}}, {upsert: true}),
ErrorCodes.DollarPrefixedFieldName);
+assert.writeErrorWithCode(
+ coll.update({"a.b": 1}, {$setOnInsert: {"_id.$invalid": 1}}, {upsert: true}),
+ ErrorCodes.DollarPrefixedFieldName);
+assert.writeErrorWithCode(coll.update({"_id.$gt": 1}, {$set: {a: 1}}, {upsert: true}),
+ ErrorCodes.DollarPrefixedFieldName);
// Replacement-style updates can contain nested $-prefixed fields.
assert.commandWorked(coll.update({"a.b": 1}, {a: {$c: 1}}));
diff --git a/src/mongo/db/update/storage_validation.cpp b/src/mongo/db/update/storage_validation.cpp
index 0feb5877ef5..c02d42a0b27 100644
--- a/src/mongo/db/update/storage_validation.cpp
+++ b/src/mongo/db/update/storage_validation.cpp
@@ -152,19 +152,30 @@ void scanDocument(const mutablebson::Document& doc,
auto currElem = doc.root().leftChild();
while (currElem.ok()) {
if (currElem.getFieldName() == idFieldName && shouldValidate) {
- uassertStatusOK(storageValidIdField(currElem.getValue()));
+ if (currElem.getType() == BSONType::Object) {
+ // We need to recursively validate the _id field while ensuring we disallow
+ // top-level $-prefix fields in the _id object.
+ scanDocument(currElem,
+ true /* deep */,
+ 0 /* recursionLevel - forces _id fields to be treated as top-level. */,
+ false /* Top-level _id fields cannot be $-prefixed. */,
+ shouldValidate,
+ containsDotsAndDollarsField);
+ } else {
+ uassertStatusOK(storageValidIdField(currElem.getValue()));
+ }
+ } else {
+ // Validate this child element.
+ const auto deep = true;
+ const uint32_t recursionLevel = 1;
+ scanDocument(currElem,
+ deep,
+ recursionLevel,
+ allowTopLevelDollarPrefixes,
+ shouldValidate,
+ containsDotsAndDollarsField);
}
- // Validate this child element.
- const auto deep = true;
- const uint32_t recursionLevel = 1;
- scanDocument(currElem,
- deep,
- recursionLevel,
- allowTopLevelDollarPrefixes,
- shouldValidate,
- containsDotsAndDollarsField);
-
currElem = currElem.rightSibling();
}
}