summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2021-09-09 15:45:17 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-09-20 23:22:54 +0000
commitf17d70733a710dee5aebb3807046bba6a23defdf (patch)
tree06c0714d9edeccd9fcb81424f9e0ff94b90fa9fa
parent2aab634ab141f0dce9c35d9805d213518cc4690a (diff)
downloadmongo-f17d70733a710dee5aebb3807046bba6a23defdf.tar.gz
SERVER-58777 Do not count empty subdocuments toward depth on insert
(cherry picked from commit 266fbb8024d99be7d288ae7da609b67884473396)
-rw-r--r--jstests/noPassthrough/write_max_user_bson_depth.js28
-rw-r--r--src/mongo/db/ops/insert.cpp7
2 files changed, 33 insertions, 2 deletions
diff --git a/jstests/noPassthrough/write_max_user_bson_depth.js b/jstests/noPassthrough/write_max_user_bson_depth.js
new file mode 100644
index 00000000000..976a5314e1c
--- /dev/null
+++ b/jstests/noPassthrough/write_max_user_bson_depth.js
@@ -0,0 +1,28 @@
+/**
+ * Tests that documents with depth equal to the max user BSON depth can be inserted, and that
+ * existing documents can be updated to have depth equal to the max user BSON depth. In particular,
+ * tests that empty subdocuments do not count toward the depth of a document.
+ */
+(function() {
+'use strict';
+
+// Max user BSON depth is 20 less than the max absolute BSON depth.
+const conn = MongoRunner.runMongod({setParameter: {maxBSONDepth: 21}});
+
+const coll = conn.getDB('test')[jsTestName()];
+
+// Can insert a document with depth equal to the max user BSON depth.
+assert.commandWorked(coll.insert({a: {}}));
+
+// Cannot insert a document with depth greater than the max user BSON depth.
+assert.commandFailedWithCode(coll.insert({a: {b: 1}}), ErrorCodes.Overflow);
+
+// Can update a document to have depth equal to the max user BSON depth.
+assert.commandWorked(coll.insert({a: 1}));
+assert.commandWorked(coll.update({a: 1}, {$set: {a: {}}}));
+
+// Cannot update a document to have depth greater than the max user BSON depth.
+assert.commandFailedWithCode(coll.update({}, {$set: {a: {b: 1}}}), ErrorCodes.Overflow);
+
+MongoRunner.stopMongod(conn);
+})();
diff --git a/src/mongo/db/ops/insert.cpp b/src/mongo/db/ops/insert.cpp
index 88da6945aa5..74e69ba4e7e 100644
--- a/src/mongo/db/ops/insert.cpp
+++ b/src/mongo/db/ops/insert.cpp
@@ -56,7 +56,10 @@ Status validateDepth(const BSONObj& obj) {
while (!frames.empty()) {
const auto elem = frames.back().next();
if (elem.type() == BSONType::Object || elem.type() == BSONType::Array) {
- if (MONGO_unlikely(frames.size() == BSONDepth::getMaxDepthForUserStorage())) {
+ auto subObj = elem.embeddedObject();
+ // Empty subdocuments do not count toward the depth of a document.
+ if (MONGO_unlikely(frames.size() == BSONDepth::getMaxDepthForUserStorage() &&
+ !subObj.isEmpty())) {
// We're exactly at the limit, so descending to the next level would exceed
// the maximum depth.
return {ErrorCodes::Overflow,
@@ -64,7 +67,7 @@ Status validateDepth(const BSONObj& obj) {
<< "cannot insert document because it exceeds "
<< BSONDepth::getMaxDepthForUserStorage() << " levels of nesting"};
}
- frames.emplace_back(elem.embeddedObject());
+ frames.emplace_back(subObj);
}
if (!frames.back().more()) {