diff options
-rw-r--r-- | jstests/noPassthrough/write_max_user_bson_depth.js | 28 | ||||
-rw-r--r-- | src/mongo/db/ops/insert.cpp | 7 |
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()) { |