summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorRichard Hausman <richard.hausman@mongodb.com>2022-08-19 17:55:53 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-08-19 19:31:00 +0000
commitd3ea0605477301d4055034dde5153267a61eb5ab (patch)
treebc1fcfa4b804ce2b713ed69f3bbc13eab897a515 /src/mongo
parent9a07ecfd7e91d330fc4cf8ea8b08e2f2e75ec04e (diff)
downloadmongo-d3ea0605477301d4055034dde5153267a61eb5ab.tar.gz
SERVER-67880 : Check BSON column is decompressible in the validate command.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/bson/SConscript6
-rw-r--r--src/mongo/bson/bson_validate.cpp27
-rw-r--r--src/mongo/bson/bson_validate.h3
-rw-r--r--src/mongo/bson/bson_validate_test.cpp121
-rw-r--r--src/mongo/bson/bsonobj.cpp4
-rw-r--r--src/mongo/bson/bsonobj.h5
-rw-r--r--src/mongo/client/SConscript1
-rw-r--r--src/mongo/client/mongo_uri_test.cpp3
-rw-r--r--src/mongo/db/SConscript5
-rw-r--r--src/mongo/db/catalog/index_build_entry_test.cpp3
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/storage/SConscript11
-rw-r--r--src/mongo/db/update/document_diff_calculator_test.cpp11
-rw-r--r--src/mongo/dbtests/jsobjtests.cpp31
-rw-r--r--src/mongo/dbtests/jsontests.cpp2
-rw-r--r--src/mongo/dbtests/querytests.cpp3
-rw-r--r--src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp21
-rw-r--r--src/mongo/util/SConscript1
19 files changed, 159 insertions, 101 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index b8bc357d941..0e831e0ff51 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -146,7 +146,6 @@ baseEnv.Library(
'base/validate_locale.cpp',
'bson/bson_comparator_interface_base.cpp',
'bson/bson_depth.cpp',
- 'bson/bson_validate.cpp',
'bson/bsonelement.cpp',
'bson/bsonmisc.cpp',
'bson/bsonobj.cpp',
diff --git a/src/mongo/bson/SConscript b/src/mongo/bson/SConscript
index 2f5c806d6f6..8781e466f00 100644
--- a/src/mongo/bson/SConscript
+++ b/src/mongo/bson/SConscript
@@ -28,6 +28,8 @@ env.CppUnitTest(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/bson/bson_validate',
+ '$BUILD_DIR/mongo/bson/util/bson_column',
],
)
@@ -38,6 +40,7 @@ env.Benchmark(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/bson/bson_validate',
],
)
@@ -52,6 +55,9 @@ env.CppLibfuzzerTest(
],
)
+env.Library(target='bson_validate', source=['bson_validate.cpp'],
+ LIBDEPS_PRIVATE=['$BUILD_DIR/mongo/bson/util/bson_column'])
+
asioEnv = env.Clone()
asioEnv.InjectThirdParty('asio')
diff --git a/src/mongo/bson/bson_validate.cpp b/src/mongo/bson/bson_validate.cpp
index d1403f07bbf..f69700696b1 100644
--- a/src/mongo/bson/bson_validate.cpp
+++ b/src/mongo/bson/bson_validate.cpp
@@ -35,6 +35,7 @@
#include "mongo/base/data_view.h"
#include "mongo/bson/bson_depth.h"
#include "mongo/bson/bsonelement.h"
+#include "mongo/bson/util/bsoncolumn.h"
#include "mongo/logv2/log.h"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kDefault
@@ -142,13 +143,14 @@ public:
l == UUIDLength);
break;
}
- case BinDataType::MD5Type:
+ case BinDataType::MD5Type: {
constexpr uint32_t md5Length = 16;
auto md5Size = ConstDataView(ptr).read<LittleEndian<uint32_t>>();
uassert(NonConformantBSON,
fmt::format("MD5 must be 16 bytes, got {} instead.", md5Size),
md5Size == md5Length);
break;
+ }
}
break;
}
@@ -222,6 +224,25 @@ class FullValidator : private ExtendedValidator {
public:
void checkNonConformantElem(const char* ptr, uint32_t offsetToValue, uint8_t type) {
ExtendedValidator::checkNonConformantElem(ptr, offsetToValue, type);
+ switch (type) {
+ case BSONType::BinData: {
+ uint8_t subtype = ConstDataView(ptr + offsetToValue + sizeof(uint32_t))
+ .read<LittleEndian<uint8_t>>();
+ switch (subtype) {
+ case BinDataType::Column: {
+ // Check for exceptions when decompressing.
+ // Calling size() decompresses the entire column.
+ try {
+ BSONColumn(BSONElement(ptr)).size();
+ } catch (...) {
+ uasserted(NonConformantBSON,
+ "Exception ocurred while decompressing a BSON column.");
+ }
+ break;
+ }
+ }
+ }
+ }
}
void checkUTF8Char() {}
@@ -490,4 +511,8 @@ Status validateBSON(const char* originalBuffer,
else
MONGO_UNREACHABLE;
}
+
+Status validateBSON(const BSONObj& obj, BSONValidateMode mode) {
+ return validateBSON(obj.objdata(), obj.objsize(), mode);
+}
} // namespace mongo
diff --git a/src/mongo/bson/bson_validate.h b/src/mongo/bson/bson_validate.h
index a748d372d39..ce79245459c 100644
--- a/src/mongo/bson/bson_validate.h
+++ b/src/mongo/bson/bson_validate.h
@@ -32,6 +32,7 @@
#include <cstdint>
#include "mongo/base/status.h"
+#include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsontypes.h"
namespace mongo {
@@ -69,4 +70,6 @@ enum class BSONValidateMode {
Status validateBSON(const char* buf,
uint64_t maxLength,
BSONValidateMode mode = BSONValidateMode::kDefault) noexcept;
+
+Status validateBSON(const BSONObj& obj, BSONValidateMode mode = BSONValidateMode::kDefault);
} // namespace mongo
diff --git a/src/mongo/bson/bson_validate_test.cpp b/src/mongo/bson/bson_validate_test.cpp
index 63a7f58056f..1c9d7b0d046 100644
--- a/src/mongo/bson/bson_validate_test.cpp
+++ b/src/mongo/bson/bson_validate_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/base/data_view.h"
#include "mongo/bson/bson_depth.h"
#include "mongo/bson/bson_validate.h"
+#include "mongo/bson/util/bsoncolumnbuilder.h"
#include "mongo/db/jsobj.h"
#include "mongo/logv2/log.h"
#include "mongo/platform/random.h"
@@ -57,10 +58,10 @@ void appendInvalidStringElement(const char* fieldName, BufBuilder* bb) {
TEST(BSONValidate, Basic) {
BSONObj x;
- ASSERT_TRUE(x.valid());
+ ASSERT_TRUE(validateBSON(x).isOK());
x = BSON("x" << 1);
- ASSERT_TRUE(x.valid());
+ ASSERT_TRUE(validateBSON(x).isOK());
}
TEST(BSONValidate, RandomData) {
@@ -86,12 +87,12 @@ TEST(BSONValidate, RandomData) {
ASSERT_EQUALS(size, o.objsize());
- if (o.valid()) {
+ if (validateBSON(o).isOK()) {
numValid++;
jsonSize += o.jsonString().size();
- ASSERT_OK(validateBSON(o.objdata(), o.objsize()));
+ ASSERT_OK(validateBSON(o));
} else {
- ASSERT_NOT_OK(validateBSON(o.objdata(), o.objsize()));
+ ASSERT_NOT_OK(validateBSON(o));
}
delete[] x;
@@ -137,12 +138,12 @@ TEST(BSONValidate, MuckingData1) {
data[i] = 0xc8U;
numToRun++;
- if (mine.valid()) {
+ if (validateBSON(mine).isOK()) {
numValid++;
jsonSize += mine.jsonString().size();
- ASSERT_OK(validateBSON(mine.objdata(), mine.objsize()));
+ ASSERT_OK(validateBSON(mine));
} else {
- ASSERT_NOT_OK(validateBSON(mine.objdata(), mine.objsize()));
+ ASSERT_NOT_OK(validateBSON(mine));
}
}
@@ -194,7 +195,7 @@ TEST(BSONValidate, Fuzz) {
// to compare outputs against (BSONObj::valid() is a wrapper for validateBSON()).
// Thus, the reason for this test is to ensure that validateBSON() doesn't trip
// any ASAN or UBSAN check when fed fuzzed input.
- validateBSON(fuzzed.objdata(), fuzzed.objsize()).isOK();
+ validateBSON(fuzzed).isOK();
}
}
@@ -202,15 +203,15 @@ TEST(BSONValidateExtended, MD5Size) {
// 16 byte string.
auto properSizeMD5 = "aaaaaaaaaaaaaaaa";
BSONObj x1 = BSON("md5" << BSONBinData(properSizeMD5, 16, MD5Type));
- ASSERT_OK(validateBSON(x1.objdata(), x1.objsize(), mongo::BSONValidateMode::kExtended));
- ASSERT_OK(validateBSON(x1.objdata(), x1.objsize(), mongo::BSONValidateMode::kFull));
+ ASSERT_OK(validateBSON(x1, mongo::BSONValidateMode::kExtended));
+ ASSERT_OK(validateBSON(x1, mongo::BSONValidateMode::kFull));
// 15 byte string.
auto improperSizeMD5 = "aaaaaaaaaaaaaaa";
BSONObj x2 = BSON("md5" << BSONBinData(improperSizeMD5, 15, MD5Type));
- Status status = validateBSON(x2.objdata(), x2.objsize(), mongo::BSONValidateMode::kExtended);
+ Status status = validateBSON(x2, mongo::BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(x2.objdata(), x2.objsize(), mongo::BSONValidateMode::kFull);
+ status = validateBSON(x2, mongo::BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
}
@@ -334,23 +335,23 @@ TEST(BSONValidateExtended, BSONArrayIndexes) {
TEST(BSONValidateFast, Empty) {
BSONObj x;
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
}
TEST(BSONValidateFast, RegEx) {
BSONObjBuilder b;
b.appendRegex("foo", "i");
BSONObj x = b.obj();
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
}
TEST(BSONValidateFast, Simple0) {
BSONObj x;
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
x = BSON("foo" << 17 << "bar"
<< "eliot");
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
}
TEST(BSONValidateFast, Simple2) {
@@ -362,7 +363,7 @@ TEST(BSONValidateFast, Simple2) {
sprintf(buf, "bar%d", i);
b.appendMaxForType(buf, i);
BSONObj x = b.obj();
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
}
}
@@ -377,14 +378,14 @@ TEST(BSONValidateFast, Simple3) {
b.appendMaxForType(buf, i);
}
BSONObj x = b.obj();
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
}
TEST(BSONValidateFast, NestedObject) {
BSONObj x = BSON("a" << 1 << "b"
<< BSON("c" << 2 << "d" << BSONArrayBuilder().obj() << "e"
<< BSON_ARRAY("1" << 2 << 3)));
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
ASSERT_NOT_OK(validateBSON(x.objdata(), x.objsize() / 2));
}
@@ -413,7 +414,7 @@ TEST(BSONValidateFast, AllTypesSimple) {
<< "18long" << 0x0123456789abcdefll // 64-bit integer
<< "19decimal" << Decimal128("0.30") // 128-bit decimal floating point
);
- ASSERT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_OK(validateBSON(x));
}
TEST(BSONValidateFast, ErrorWithId) {
@@ -422,7 +423,7 @@ TEST(BSONValidateFast, ErrorWithId) {
ob.append("_id", 1);
appendInvalidStringElement("not_id", &bb);
const BSONObj x = ob.done();
- const Status status = validateBSON(x.objdata(), x.objsize());
+ const Status status = validateBSON(x);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(
status.reason(),
@@ -435,7 +436,7 @@ TEST(BSONValidateFast, ErrorBeforeId) {
appendInvalidStringElement("not_id", &bb);
ob.append("_id", 1);
const BSONObj x = ob.done();
- const Status status = validateBSON(x.objdata(), x.objsize());
+ const Status status = validateBSON(x);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(status.reason(),
"Not null terminated string in element with field name 'not_id' in object with "
@@ -447,7 +448,7 @@ TEST(BSONValidateFast, ErrorNoId) {
BSONObjBuilder ob(bb);
appendInvalidStringElement("not_id", &bb);
const BSONObj x = ob.done();
- const Status status = validateBSON(x.objdata(), x.objsize());
+ const Status status = validateBSON(x);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(status.reason(),
"Not null terminated string in element with field name 'not_id' in object with "
@@ -459,7 +460,7 @@ TEST(BSONValidateFast, ErrorIsInId) {
BSONObjBuilder ob(bb);
appendInvalidStringElement("_id", &bb);
const BSONObj x = ob.done();
- const Status status = validateBSON(x.objdata(), x.objsize());
+ const Status status = validateBSON(x);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(
status.reason(),
@@ -474,7 +475,7 @@ TEST(BSONValidateFast, NonTopLevelId) {
<< "not the real _id"));
appendInvalidStringElement("not_id2", &bb);
const BSONObj x = ob.done();
- const Status status = validateBSON(x.objdata(), x.objsize());
+ const Status status = validateBSON(x);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(status.reason(),
"Not null terminated string in element with field name 'not_id2' in object with "
@@ -490,7 +491,7 @@ TEST(BSONValidateFast, ErrorInNestedObjectWithId) {
const BSONObj x = BSON("_id" << 1 << "nested"
<< BSON_ARRAY("a"
<< "b" << nestedInvalid));
- const Status status = validateBSON(x.objdata(), x.objsize());
+ const Status status = validateBSON(x);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(status.reason(),
"Not null terminated string in element with field name 'nested.2.invalid' "
@@ -510,14 +511,14 @@ TEST(BSONValidateFast, StringHasSomething) {
+ 4 // size
,
x.objsize());
- ASSERT_NOT_OK(validateBSON(x.objdata(), x.objsize()));
+ ASSERT_NOT_OK(validateBSON(x));
}
TEST(BSONValidateFast, BoolValuesAreValidated) {
BSONObjBuilder bob;
bob.append("x", false);
const BSONObj obj = bob.done();
- ASSERT_OK(validateBSON(obj.objdata(), obj.objsize()));
+ ASSERT_OK(validateBSON(obj));
const BSONElement x = obj["x"];
// Legal, because we know that the BufBuilder gave
// us back some heap memory, which isn't oringinally const.
@@ -527,9 +528,9 @@ TEST(BSONValidateFast, BoolValuesAreValidated) {
++val) {
*writable = static_cast<char>(val);
if ((val == 0) || (val == 1)) {
- ASSERT_OK(validateBSON(obj.objdata(), obj.objsize()));
+ ASSERT_OK(validateBSON(obj));
} else {
- ASSERT_NOT_OK(validateBSON(obj.objdata(), obj.objsize()));
+ ASSERT_NOT_OK(validateBSON(obj));
}
}
}
@@ -542,7 +543,7 @@ TEST(BSONValidateFast, InvalidType) {
BSONObj obj(buffer);
// Validate fails.
- ASSERT_NOT_OK(validateBSON(obj.objdata(), obj.objsize()));
+ ASSERT_NOT_OK(validateBSON(obj));
// Make sure the binary buffer above indeed has the invalid type.
ASSERT_THROWS_CODE(obj.woCompare(BSON("A" << 1)), DBException, 10320);
@@ -550,9 +551,9 @@ TEST(BSONValidateFast, InvalidType) {
TEST(BSONValidateFast, ValidCodeWScope) {
BSONObj obj = BSON("a" << BSONCodeWScope("code", BSON("c" << BSONObj())));
- ASSERT_OK(validateBSON(obj.objdata(), obj.objsize()));
+ ASSERT_OK(validateBSON(obj));
obj = BSON("a" << BSONCodeWScope("code", BSON("c" << BSONArray() << "d" << BSONArray())));
- ASSERT_OK(validateBSON(obj.objdata(), obj.objsize()));
+ ASSERT_OK(validateBSON(obj));
}
BSONObj nest(int nesting) {
@@ -561,10 +562,10 @@ BSONObj nest(int nesting) {
TEST(BSONValidateFast, MaxNestingDepth) {
BSONObj maxNesting = nest(BSONDepth::getMaxAllowableDepth());
- ASSERT_OK(validateBSON(maxNesting.objdata(), maxNesting.objsize()));
+ ASSERT_OK(validateBSON(maxNesting));
BSONObj tooDeepNesting = nest(BSONDepth::getMaxAllowableDepth() + 1);
- Status status = validateBSON(tooDeepNesting.objdata(), tooDeepNesting.objsize());
+ Status status = validateBSON(tooDeepNesting);
ASSERT_EQ(status.code(), ErrorCodes::Overflow);
}
@@ -601,8 +602,8 @@ TEST(BSONValidateExtended, UUIDLength) {
// Checks that an invalid UUID length (!= 16 bytes) throws a warning.
std::pair<Status, Status> stats{Status::OK(), Status::OK()};
auto fullyValidate = [&](BSONObj obj) {
- return std::pair{validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended),
- validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull)};
+ return std::pair{validateBSON(obj, BSONValidateMode::kExtended),
+ validateBSON(obj, BSONValidateMode::kFull)};
};
BSONObj x = BSON("u" << BSONBinData("de", 2, BinDataType::newUUID));
stats = fullyValidate(x);
@@ -622,39 +623,59 @@ TEST(BSONValidateExtended, UUIDLength) {
TEST(BSONValidateExtended, DeprecatedTypes) {
BSONObj obj = BSON("a" << BSONUndefined);
- Status status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended);
+ Status status = validateBSON(obj, BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull);
+ status = validateBSON(obj, BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
obj = BSON("b" << BSONDBRef("db", OID("dbdbdbdbdbdbdbdbdbdbdbdb")));
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended);
+ status = validateBSON(obj, BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull);
+ status = validateBSON(obj, BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
obj = BSON("c" << BSONSymbol("symbol"));
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended);
+ status = validateBSON(obj, BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull);
+ status = validateBSON(obj, BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
obj = BSON("d" << BSONCodeWScope("(function(){})();", BSON("a" << 1)));
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended);
+ status = validateBSON(obj, BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull);
+ status = validateBSON(obj, BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
obj = BSON("e" << BSONBinData("", 0, ByteArrayDeprecated));
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended);
+ status = validateBSON(obj, BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull);
+ status = validateBSON(obj, BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
obj = BSON("f" << BSONBinData("", 0, bdtUUID));
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kExtended);
+ status = validateBSON(obj, BSONValidateMode::kExtended);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
- status = validateBSON(obj.objdata(), obj.objsize(), BSONValidateMode::kFull);
+ status = validateBSON(obj, BSONValidateMode::kFull);
ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
}
+
+TEST(BSONValidateExtended, BSONColumn) {
+ BSONColumnBuilder cb("example"_sd);
+ cb.append(BSON("a"
+ << "deadbeef")
+ .getField("a"));
+ BSONBinData columnData = cb.finalize();
+ BSONObj obj = BSON("a" << columnData);
+ Status status = validateBSON(obj, BSONValidateMode::kFull);
+ ASSERT_OK(status);
+
+ // Change one important byte.
+ ((char*)columnData.data)[0] = '0';
+ obj = BSON("a" << columnData);
+ status = validateBSON(obj, BSONValidateMode::kExtended);
+ ASSERT_OK(status);
+ status = validateBSON(obj, BSONValidateMode::kFull);
+ ASSERT_EQ(status.code(), ErrorCodes::NonConformantBSON);
+}
+
} // namespace
diff --git a/src/mongo/bson/bsonobj.cpp b/src/mongo/bson/bsonobj.cpp
index 6566398a883..0149eeece7d 100644
--- a/src/mongo/bson/bsonobj.cpp
+++ b/src/mongo/bson/bsonobj.cpp
@@ -32,7 +32,6 @@
#include "mongo/db/jsobj.h"
#include "mongo/base/data_range.h"
-#include "mongo/bson/bson_validate.h"
#include "mongo/bson/bsonelement_comparator_interface.h"
#include "mongo/bson/generator_extended_canonical_2_0_0.h"
#include "mongo/bson/generator_extended_relaxed_2_0_0.h"
@@ -300,9 +299,6 @@ BSONObj BSONObj::jsonStringBuffer(JsonStringFormat format,
}
}
-bool BSONObj::valid() const {
- return validateBSON(objdata(), objsize()).isOK();
-}
int BSONObj::woCompare(const BSONObj& r,
const Ordering& o,
diff --git a/src/mongo/bson/bsonobj.h b/src/mongo/bson/bsonobj.h
index a5270adfd25..1a51b370678 100644
--- a/src/mongo/bson/bsonobj.h
+++ b/src/mongo/bson/bsonobj.h
@@ -638,11 +638,6 @@ public:
bool hasFieldNames() const;
/**
- * Returns true if this object is valid and returns false otherwise.
- */
- bool valid() const;
-
- /**
* add all elements of the object to the specified vector
*/
void elems(std::vector<BSONElement>&) const;
diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript
index 25df63559cc..cd21400ca2b 100644
--- a/src/mongo/client/SConscript
+++ b/src/mongo/client/SConscript
@@ -71,6 +71,7 @@ if get_option('ssl') == 'on':
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/db/server_options_core', # For object_check.h
'$BUILD_DIR/mongo/idl/idl_parser',
'$BUILD_DIR/third_party/shim_kms_message',
diff --git a/src/mongo/client/mongo_uri_test.cpp b/src/mongo/client/mongo_uri_test.cpp
index f0cb567b75d..2555121ae0f 100644
--- a/src/mongo/client/mongo_uri_test.cpp
+++ b/src/mongo/client/mongo_uri_test.cpp
@@ -33,6 +33,7 @@
#include <fstream>
#include "mongo/base/string_data.h"
+#include "mongo/bson/bson_validate.h"
#include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsontypes.h"
#include "mongo/bson/json.h"
@@ -583,7 +584,7 @@ BSONObj getBsonFromJsonFile(std::string fileName) {
std::ifstream infile(filename.c_str());
std::string data((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
BSONObj obj = fromjson(data);
- ASSERT_TRUE(obj.valid());
+ ASSERT_TRUE(validateBSON(obj).isOK());
ASSERT_TRUE(obj.hasField("tests"));
BSONObj arr = obj.getField("tests").embeddedObject().getOwned();
ASSERT_TRUE(arr.couldBeArray());
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 4f3c7fef780..200c6878ab7 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -277,6 +277,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/bson/bson_validate',
],
)
@@ -292,6 +293,7 @@ env.Library(
'server_options_core',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/idl/server_parameter',
'$BUILD_DIR/mongo/util/fail_point',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
@@ -600,6 +602,7 @@ env.Library(
'write_concern_options',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/db/storage/storage_change_lock',
'$BUILD_DIR/mongo/util/processinfo',
],
@@ -997,6 +1000,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/db/audit',
'$BUILD_DIR/mongo/db/auth/auth',
'$BUILD_DIR/mongo/db/auth/auth_umc',
@@ -1297,6 +1301,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/db/catalog/clustered_collection_options',
'$BUILD_DIR/mongo/db/query/collation/collator_interface',
'$BUILD_DIR/mongo/db/storage/key_string',
diff --git a/src/mongo/db/catalog/index_build_entry_test.cpp b/src/mongo/db/catalog/index_build_entry_test.cpp
index 6aa53a8a2ba..dc0972f3085 100644
--- a/src/mongo/db/catalog/index_build_entry_test.cpp
+++ b/src/mongo/db/catalog/index_build_entry_test.cpp
@@ -32,6 +32,7 @@
#include <string>
#include <vector>
+#include "mongo/bson/bson_validate.h"
#include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/bson/bsontypes.h"
@@ -124,7 +125,7 @@ TEST(IndexBuildEntryTest, SerializeAndDeserialize) {
entry.setCommitReadyMembers(generateCommitReadyMembers(3));
BSONObj obj = entry.toBSON();
- ASSERT_TRUE(obj.valid());
+ ASSERT_TRUE(validateBSON(obj).isOK());
IDLParserContext ctx("IndexBuildsEntry Parser");
IndexBuildEntry rebuiltEntry = IndexBuildEntry::parse(ctx, obj);
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index d058ade3878..f25afb27939 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -514,6 +514,7 @@ env.Library(
'shutdown.idl',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/bson/bson_validate',
'$BUILD_DIR/mongo/idl/idl_parser',
'$BUILD_DIR/mongo/util/fail_point',
],
diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript
index 86c58de6253..0aeb72b0d83 100644
--- a/src/mongo/db/storage/SConscript
+++ b/src/mongo/db/storage/SConscript
@@ -383,16 +383,15 @@ env.Library(
)
env.Library(
- target='storage_engine_metadata',
- source=[
+ target='storage_engine_metadata', source=[
'storage_engine_metadata.cpp',
- ],
- LIBDEPS=[
+ ], LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/server_options_core',
- ],
-)
+ ], LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/bson/bson_validate',
+ ])
env.Library(
target='storage_file_util',
diff --git a/src/mongo/db/update/document_diff_calculator_test.cpp b/src/mongo/db/update/document_diff_calculator_test.cpp
index 55a05051021..feaeb9343be 100644
--- a/src/mongo/db/update/document_diff_calculator_test.cpp
+++ b/src/mongo/db/update/document_diff_calculator_test.cpp
@@ -32,6 +32,7 @@
#include <functional>
#include "mongo/bson/bson_depth.h"
+#include "mongo/bson/bson_validate.h"
#include "mongo/bson/json.h"
#include "mongo/db/update/document_diff_calculator.h"
#include "mongo/unittest/unittest.h"
@@ -295,7 +296,7 @@ TEST(DocumentDiffCalculatorTest, DeeplyNestObjectGenerateDiff) {
preBob.append("largeField", largeValue);
buildDeepObj(&preBob, "subObj", 0, maxDepth, functionToApply);
auto preObj = preBob.done();
- ASSERT(preObj.valid());
+ ASSERT_OK(validateBSON(preObj));
BSONObjBuilder postBob;
postBob.append("largeField", largeValue);
@@ -312,7 +313,7 @@ TEST(DocumentDiffCalculatorTest, DeeplyNestObjectGenerateDiff) {
// Deleting the deepest field should give the post object.
diffOutput = doc_diff::computeDiff(preObj, postBob2.done(), 0, nullptr);
ASSERT(diffOutput);
- ASSERT(diffOutput->diff.valid());
+ ASSERT_OK(validateBSON(diffOutput->diff));
BSONObjBuilder expectedOutputBuilder;
buildDeepObj(&expectedOutputBuilder,
@@ -341,17 +342,17 @@ TEST(DocumentDiffCalculatorTest, DeepestObjectSubDiff) {
value = 1;
buildDeepObj(&bob1, "subObj", 0, BSONDepth::getMaxDepthForUserStorage(), functionToApply);
auto preObj = bob1.done();
- ASSERT(preObj.valid());
+ ASSERT_OK(validateBSON(preObj));
BSONObjBuilder postBob;
value = 2;
buildDeepObj(&postBob, "subObj", 0, BSONDepth::getMaxDepthForUserStorage(), functionToApply);
auto postObj = postBob.done();
- ASSERT(postObj.valid());
+ ASSERT_OK(validateBSON(postObj));
auto diffOutput = doc_diff::computeDiff(preObj, postObj, 0, nullptr);
ASSERT(diffOutput);
- ASSERT(diffOutput->diff.valid());
+ ASSERT_OK(validateBSON(diffOutput->diff));
BSONObjBuilder expectedOutputBuilder;
buildDeepObj(&expectedOutputBuilder,
diff --git a/src/mongo/dbtests/jsobjtests.cpp b/src/mongo/dbtests/jsobjtests.cpp
index a79bf0bbf9b..37da3d64aa7 100644
--- a/src/mongo/dbtests/jsobjtests.cpp
+++ b/src/mongo/dbtests/jsobjtests.cpp
@@ -37,6 +37,7 @@
#include <cmath>
#include <iostream>
+#include "mongo/bson/bson_validate.h"
#include "mongo/bson/bsonobj_comparator.h"
#include "mongo/bson/simple_bsonelement_comparator.h"
#include "mongo/bson/util/builder.h"
@@ -507,7 +508,7 @@ public:
bb << "a" << 1;
BSONObj tmp = bb.asTempObj();
ASSERT(tmp.objsize() == 4 + (1 + 2 + 4) + 1);
- ASSERT(tmp.valid());
+ ASSERT(validateBSON(tmp).isOK());
ASSERT(tmp.hasField("a"));
ASSERT(!tmp.hasField("b"));
ASSERT_BSONOBJ_EQ(tmp, BSON("a" << 1));
@@ -515,7 +516,7 @@ public:
bb << "b" << 2;
BSONObj obj = bb.obj();
ASSERT_EQUALS(obj.objsize(), 4 + (1 + 2 + 4) + (1 + 2 + 4) + 1);
- ASSERT(obj.valid());
+ ASSERT(validateBSON(obj).isOK());
ASSERT(obj.hasField("a"));
ASSERT(obj.hasField("b"));
ASSERT_BSONOBJ_EQ(obj, BSON("a" << 1 << "b" << 2));
@@ -525,7 +526,7 @@ public:
bb << "a" << GT << 1;
BSONObj tmp = bb.asTempObj();
ASSERT(tmp.objsize() == 4 + (1 + 2 + (4 + 1 + 4 + 4 + 1)) + 1);
- ASSERT(tmp.valid());
+ ASSERT(validateBSON(tmp).isOK());
ASSERT(tmp.hasField("a"));
ASSERT(!tmp.hasField("b"));
ASSERT_BSONOBJ_EQ(tmp, BSON("a" << BSON("$gt" << 1)));
@@ -534,7 +535,7 @@ public:
BSONObj obj = bb.obj();
ASSERT(obj.objsize() ==
4 + (1 + 2 + (4 + 1 + 4 + 4 + 1)) + (1 + 2 + (4 + 1 + 4 + 4 + 1)) + 1);
- ASSERT(obj.valid());
+ ASSERT(validateBSON(obj).isOK());
ASSERT(obj.hasField("a"));
ASSERT(obj.hasField("b"));
ASSERT_BSONOBJ_EQ(obj, BSON("a" << BSON("$gt" << 1) << "b" << BSON("$lt" << 2)));
@@ -544,7 +545,7 @@ public:
bb << "a" << 1;
BSONObj tmp = bb.asTempObj();
ASSERT(tmp.objsize() == 4 + (1 + 2 + 4) + 1);
- ASSERT(tmp.valid());
+ ASSERT(validateBSON(tmp).isOK());
ASSERT(tmp.hasField("a"));
ASSERT(!tmp.hasField("b"));
ASSERT_BSONOBJ_EQ(tmp, BSON("a" << 1));
@@ -556,7 +557,7 @@ public:
}
bb << "b" << arr.arr();
BSONObj obj = bb.obj();
- ASSERT(obj.valid());
+ ASSERT(validateBSON(obj).isOK());
ASSERT(obj.hasField("a"));
ASSERT(obj.hasField("b"));
}
@@ -758,8 +759,8 @@ class Base {
public:
virtual ~Base() {}
void run() {
- ASSERT(valid().valid());
- ASSERT(!invalid().valid());
+ ASSERT(validateBSON(valid()).isOK());
+ ASSERT(!validateBSON(invalid()).isOK());
}
protected:
@@ -808,7 +809,7 @@ public:
b.appendNull("a");
BSONObj o = b.done();
set(o, 4, mongo::Undefined);
- ASSERT(o.valid());
+ ASSERT(validateBSON(o).isOK());
}
};
@@ -992,7 +993,7 @@ public:
void run() {
const char data[] = {0x07, 0x00, 0x00, 0x00, char(type_), 'a', 0x00};
BSONObj o(data);
- ASSERT(!o.valid());
+ ASSERT(!validateBSON(o).isOK());
}
private:
@@ -1331,7 +1332,7 @@ public:
b2.done();
b1.append("f", 10.0);
BSONObj ret = b1.done();
- ASSERT(ret.valid());
+ ASSERT(validateBSON(ret).isOK());
ASSERT(ret.woCompare(fromjson("{a:'bcd',foo:{ggg:44},f:10}")) == 0);
}
};
@@ -1352,7 +1353,7 @@ public:
BSONObj o = BSON("now" << DATENOW);
Date_t after = jsTime();
- ASSERT(o.valid());
+ ASSERT(validateBSON(o).isOK());
BSONElement e = o["now"];
ASSERT(e.type() == Date);
@@ -1370,7 +1371,7 @@ public:
b.appendTimeT("now", aTime);
BSONObj o = b.obj();
- ASSERT(o.valid());
+ ASSERT(validateBSON(o).isOK());
BSONElement e = o["now"];
ASSERT_EQUALS(Date, e.type());
@@ -1384,8 +1385,8 @@ public:
BSONObj min = BSON("a" << MINKEY);
BSONObj max = BSON("b" << MAXKEY);
- ASSERT(min.valid());
- ASSERT(max.valid());
+ ASSERT(validateBSON(min).isOK());
+ ASSERT(validateBSON(max).isOK());
BSONElement minElement = min["a"];
BSONElement maxElement = max["b"];
diff --git a/src/mongo/dbtests/jsontests.cpp b/src/mongo/dbtests/jsontests.cpp
index 7fd425e3ad7..125e7ae63c5 100644
--- a/src/mongo/dbtests/jsontests.cpp
+++ b/src/mongo/dbtests/jsontests.cpp
@@ -625,7 +625,7 @@ void assertEquals(const std::string& json,
}
void checkEquivalence(const std::string& json, const BSONObj& bson) {
- ASSERT(fromjson(json).valid());
+ ASSERT(validateBSON(fromjson(json)).isOK());
assertEquals(json, bson, fromjson(json), "mode: json-to-bson");
assertEquals(json, bson, fromjson(tojson(bson)), "mode: <default>");
assertEquals(json, bson, fromjson(tojson(bson, LegacyStrict)), "mode: strict");
diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp
index 1e5407d62b5..677764e3d3b 100644
--- a/src/mongo/dbtests/querytests.cpp
+++ b/src/mongo/dbtests/querytests.cpp
@@ -30,6 +30,7 @@
#include <boost/optional.hpp>
#include <iostream>
+#include "mongo/bson/bson_validate.h"
#include "mongo/client/dbclient_cursor.h"
#include "mongo/db/catalog/collection_write_path.h"
#include "mongo/db/catalog/multi_index_block.h"
@@ -1204,7 +1205,7 @@ public:
std::unique_ptr<DBClientCursor> cursor = _client.find(std::move(findRequest));
while (cursor->more()) {
BSONObj o = cursor->next();
- verify(o.valid());
+ verify(validateBSON(o).isOK());
}
}
void run() {
diff --git a/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp b/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp
index c875b0d16b0..d094003f515 100644
--- a/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp
+++ b/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp
@@ -35,6 +35,7 @@
#include <yaml-cpp/yaml.h>
#include "mongo/base/initializer.h"
+#include "mongo/bson/bson_validate.h"
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/commands/test_commands_enabled.h"
#include "mongo/db/json.h"
@@ -195,7 +196,7 @@ protected:
// convert the message into an OpMessage to examine its BSON
auto outputOpMsg = mongo::OpMsg::parseOwned(outputMessage);
- ASSERT(outputOpMsg.body.valid());
+ ASSERT_OK(validateBSON(outputOpMsg.body));
return outputOpMsg.body;
}
@@ -408,7 +409,7 @@ TEST_F(MongodbCAPITest, ReadDB) {
auto outputBSON = performRpc(client, findMsg);
- ASSERT(outputBSON.valid());
+ ASSERT_OK(validateBSON(outputBSON));
ASSERT(outputBSON.hasField("cursor"));
ASSERT(outputBSON.getField("cursor").embeddedObject().hasField("firstBatch"));
mongo::BSONObj arrObj =
@@ -433,7 +434,7 @@ TEST_F(MongodbCAPITest, InsertAndRead) {
"{insert: 'collection_name', documents: [{firstName: 'Mongo', lastName: 'DB', age: 10}]}");
auto insertOpMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", insertObj);
auto outputBSON1 = performRpc(client, insertOpMsg);
- ASSERT(outputBSON1.valid());
+ ASSERT_OK(validateBSON(outputBSON1));
ASSERT(outputBSON1.hasField("n"));
ASSERT(outputBSON1.getIntField("n") == 1);
ASSERT(outputBSON1.hasField("ok"));
@@ -442,7 +443,7 @@ TEST_F(MongodbCAPITest, InsertAndRead) {
mongo::BSONObj findObj = mongo::fromjson("{find: 'collection_name', limit: 1}");
auto findMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", findObj);
auto outputBSON2 = performRpc(client, findMsg);
- ASSERT(outputBSON2.valid());
+ ASSERT_OK(validateBSON(outputBSON2));
ASSERT(outputBSON2.hasField("cursor"));
ASSERT(outputBSON2.getField("cursor").embeddedObject().hasField("firstBatch"));
mongo::BSONObj arrObj =
@@ -468,7 +469,7 @@ TEST_F(MongodbCAPITest, InsertAndReadDifferentClients) {
"{insert: 'collection_name', documents: [{firstName: 'Mongo', lastName: 'DB', age: 10}]}");
auto insertOpMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", insertObj);
auto outputBSON1 = performRpc(client1, insertOpMsg);
- ASSERT(outputBSON1.valid());
+ ASSERT_OK(validateBSON(outputBSON1));
ASSERT(outputBSON1.hasField("n"));
ASSERT(outputBSON1.getIntField("n") == 1);
ASSERT(outputBSON1.hasField("ok"));
@@ -477,7 +478,7 @@ TEST_F(MongodbCAPITest, InsertAndReadDifferentClients) {
mongo::BSONObj findObj = mongo::fromjson("{find: 'collection_name', limit: 1}");
auto findMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", findObj);
auto outputBSON2 = performRpc(client2, findMsg);
- ASSERT(outputBSON2.valid());
+ ASSERT_OK(validateBSON(outputBSON2));
ASSERT(outputBSON2.hasField("cursor"));
ASSERT(outputBSON2.getField("cursor").embeddedObject().hasField("firstBatch"));
mongo::BSONObj arrObj =
@@ -502,7 +503,7 @@ TEST_F(MongodbCAPITest, InsertAndDelete) {
"age: 10}]}");
auto insertOpMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", insertObj);
auto outputBSON1 = performRpc(client, insertOpMsg);
- ASSERT(outputBSON1.valid());
+ ASSERT_OK(validateBSON(outputBSON1));
ASSERT(outputBSON1.hasField("n"));
ASSERT(outputBSON1.getIntField("n") == 1);
ASSERT(outputBSON1.hasField("ok"));
@@ -515,7 +516,7 @@ TEST_F(MongodbCAPITest, InsertAndDelete) {
"1}]}");
auto deleteOpMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", deleteObj);
auto outputBSON2 = performRpc(client, deleteOpMsg);
- ASSERT(outputBSON2.valid());
+ ASSERT_OK(validateBSON(outputBSON2));
ASSERT(outputBSON2.hasField("n"));
ASSERT(outputBSON2.getIntField("n") == 1);
ASSERT(outputBSON2.hasField("ok"));
@@ -531,7 +532,7 @@ TEST_F(MongodbCAPITest, InsertAndUpdate) {
"age: 10}]}");
auto insertOpMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", insertObj);
auto outputBSON1 = performRpc(client, insertOpMsg);
- ASSERT(outputBSON1.valid());
+ ASSERT_OK(validateBSON(outputBSON1));
ASSERT(outputBSON1.hasField("n"));
ASSERT(outputBSON1.getIntField("n") == 1);
ASSERT(outputBSON1.hasField("ok"));
@@ -544,7 +545,7 @@ TEST_F(MongodbCAPITest, InsertAndUpdate) {
"{age: 5}}}]}");
auto updateOpMsg = mongo::OpMsgRequest::fromDBAndBody("db_name", updateObj);
auto outputBSON2 = performRpc(client, updateOpMsg);
- ASSERT(outputBSON2.valid());
+ ASSERT_OK(validateBSON(outputBSON2));
ASSERT(outputBSON2.hasField("ok"));
ASSERT(outputBSON2.getField("ok").numberDouble() == 1.0);
ASSERT(outputBSON2.hasField("nModified"));
diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript
index 55a2d9b2a74..21ae0493f40 100644
--- a/src/mongo/util/SConscript
+++ b/src/mongo/util/SConscript
@@ -225,6 +225,7 @@ env.Library(
],
LIBDEPS=[
"$BUILD_DIR/mongo/base",
+ '$BUILD_DIR/mongo/bson/bson_validate',
"$BUILD_DIR/mongo/idl/server_parameter",
],
)