summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2021-12-13 12:15:08 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-12-16 18:53:43 +0000
commit80d2987ad08a9f6a187b0df19b1ca1d7462a9e02 (patch)
treec99f42ebd0c5dede38192cd98369019e6e9704ce
parent817e61d303996e944c4c14e8df14b73f1eb15381 (diff)
downloadmongo-80d2987ad08a9f6a187b0df19b1ca1d7462a9e02.tar.gz
SERVER-61846 redact document using null instead of default mask to stay under BSON limit
(cherry picked from commit 886e09ce457d5cdbef16710678c386ec6765db3c)
-rw-r--r--src/mongo/bson/bsonobj.cpp23
-rw-r--r--src/mongo/logv2/redaction_test.cpp6
2 files changed, 21 insertions, 8 deletions
diff --git a/src/mongo/bson/bsonobj.cpp b/src/mongo/bson/bsonobj.cpp
index 53c7f313289..33ce012139b 100644
--- a/src/mongo/bson/bsonobj.cpp
+++ b/src/mongo/bson/bsonobj.cpp
@@ -143,25 +143,38 @@ BSONObj BSONObj::redact() const {
// Helper to get an "internal function" to be able to do recursion
struct redactor {
- void operator()(BSONObjBuilder& builder, const BSONObj& obj) {
+ void operator()(BSONObjBuilder& builder, const BSONObj& obj, bool appendMask) {
for (BSONElement e : obj) {
if (e.type() == Object) {
BSONObjBuilder subBuilder = builder.subobjStart(e.fieldNameStringData());
- operator()(subBuilder, e.Obj());
+ operator()(subBuilder, e.Obj(), appendMask);
subBuilder.done();
} else if (e.type() == Array) {
BSONObjBuilder subBuilder = builder.subarrayStart(e.fieldNameStringData());
- operator()(subBuilder, e.Obj());
+ operator()(subBuilder, e.Obj(), appendMask);
subBuilder.done();
- } else {
+ } else if (appendMask) {
builder.append(e.fieldNameStringData(), "###"_sd);
+ } else {
+ builder.appendNull(e.fieldNameStringData());
}
}
}
};
+ try {
+ BSONObjBuilder builder;
+ redactor()(builder, *this, /*appendMask=*/true);
+ return builder.obj();
+ } catch (const ExceptionFor<ErrorCodes::BSONObjectTooLarge>&) {
+ }
+
+ // For some BSONObj with lots of small fields, replacing each element's value with the default
+ // redaction mask "###" may cause us to exceed the maximum allowed BSON size. In this case,
+ // we use BSONType::jstNull, which ensures the redacted object will not be larger than the
+ // original.
BSONObjBuilder builder;
- redactor()(builder, *this);
+ redactor()(builder, *this, /*appendMask=*/false);
return builder.obj();
}
diff --git a/src/mongo/logv2/redaction_test.cpp b/src/mongo/logv2/redaction_test.cpp
index 8ab293822c2..bc22f60b4ae 100644
--- a/src/mongo/logv2/redaction_test.cpp
+++ b/src/mongo/logv2/redaction_test.cpp
@@ -155,7 +155,7 @@ TEST(RedactBSONTest, BSONWithArrays) {
testBSONCases(testCases);
}
-TEST(RedactBSONTest, RedactCausesBSONTooLarge) {
+TEST(RedactBSONTest, RedactedObjectShouldBeSmallerOrEqualInSizeToOriginal) {
logv2::setShouldRedactLogs(true);
BSONObjBuilder bob;
for (int i = 0; i < 1024 * 1024; i++) {
@@ -164,8 +164,8 @@ TEST(RedactBSONTest, RedactCausesBSONTooLarge) {
bob.append(fieldName, 1);
}
const auto obj = bob.obj();
- // Demonstrates it is possible to grow a BSON too large by redacting fields.
- ASSERT_THROWS_CODE(redact(obj), DBException, ErrorCodes::BSONObjectTooLarge);
+ const auto redactedObj = redact(obj);
+ ASSERT_LTE(redactedObj.objsize(), obj.objsize());
}
} // namespace
} // namespace mongo