diff options
author | Jonathan Reams <jbreams@mongodb.com> | 2019-08-07 11:08:12 -0400 |
---|---|---|
committer | Jonathan Reams <jbreams@mongodb.com> | 2019-08-07 13:39:28 -0400 |
commit | d7455e67f5b002de110f7972603906888aff66b8 (patch) | |
tree | 7272978897869431e642faa0f4b20119042984fc | |
parent | 6978f67e7b4d86cf5cea0970ef7e3f9d8566bb29 (diff) | |
download | mongo-d7455e67f5b002de110f7972603906888aff66b8.tar.gz |
SERVER-42657 Make DataType<BSONObj> noexcept safe
-rw-r--r-- | src/mongo/bson/bsonobj.cpp | 9 | ||||
-rw-r--r-- | src/mongo/bson/bsonobj.h | 6 | ||||
-rw-r--r-- | src/mongo/rpc/op_msg_integration_test.cpp | 29 |
3 files changed, 40 insertions, 4 deletions
diff --git a/src/mongo/bson/bsonobj.cpp b/src/mongo/bson/bsonobj.cpp index 07aab647110..5985ec18976 100644 --- a/src/mongo/bson/bsonobj.cpp +++ b/src/mongo/bson/bsonobj.cpp @@ -622,8 +622,11 @@ void BSONObj::toString( s << (isArray ? " ]" : " }"); } -Status DataType::Handler<BSONObj>::store( - const BSONObj& bson, char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) { +Status DataType::Handler<BSONObj>::store(const BSONObj& bson, + char* ptr, + size_t length, + size_t* advanced, + std::ptrdiff_t debug_offset) noexcept try { if (bson.objsize() > static_cast<int>(length)) { str::stream ss; ss << "buffer too small to write bson of size (" << bson.objsize() @@ -640,6 +643,8 @@ Status DataType::Handler<BSONObj>::store( } return Status::OK(); +} catch (const DBException& e) { + return e.toStatus(); } std::ostream& operator<<(std::ostream& s, const BSONObj& o) { diff --git a/src/mongo/bson/bsonobj.h b/src/mongo/bson/bsonobj.h index d05108706ee..82efac98902 100644 --- a/src/mongo/bson/bsonobj.h +++ b/src/mongo/bson/bsonobj.h @@ -829,7 +829,7 @@ struct DataType::Handler<BSONObj> { const char* ptr, size_t length, size_t* advanced, - std::ptrdiff_t debug_offset) { + std::ptrdiff_t debug_offset) noexcept try { auto temp = BSONObj(ptr); auto len = temp.objsize(); if (bson) { @@ -839,13 +839,15 @@ struct DataType::Handler<BSONObj> { *advanced = len; } return Status::OK(); + } catch (const DBException& e) { + return e.toStatus(); } static Status store(const BSONObj& bson, char* ptr, size_t length, size_t* advanced, - std::ptrdiff_t debug_offset); + std::ptrdiff_t debug_offset) noexcept; static BSONObj defaultConstruct() { return BSONObj(); diff --git a/src/mongo/rpc/op_msg_integration_test.cpp b/src/mongo/rpc/op_msg_integration_test.cpp index 7aa41d66cb1..8ee613a3616 100644 --- a/src/mongo/rpc/op_msg_integration_test.cpp +++ b/src/mongo/rpc/op_msg_integration_test.cpp @@ -468,4 +468,33 @@ TEST(OpMsg, ServerRepliesWithoutChecksumToRequestWithoutChecksum) { TEST(OpMsg, ServerRepliesWithChecksumToRequestWithChecksum) { checksumTest(true); } + +TEST(OpMsg, ServerHandlesReallyLargeMessagesGracefully) { + std::string errMsg; + auto conn = unittest::getFixtureConnectionString().connect("integration_test", errMsg); + uassert(ErrorCodes::SocketException, errMsg, conn); + + auto buildInfo = conn->runCommand(OpMsgRequest::fromDBAndBody("admin", BSON("buildInfo" << 1))) + ->getCommandReply(); + ASSERT_OK(getStatusFromCommandResult(buildInfo)); + const auto maxBSONObjSizeFromServer = + static_cast<size_t>(buildInfo["maxBsonObjectSize"].Number()); + const std::string bigData(maxBSONObjSizeFromServer * 2, ' '); + + BSONObjBuilder bob; + bob << "ismaster" << 1 << "ignoredField" << bigData << "$db" + << "admin"; + OpMsgRequest request; + request.body = bob.obj<BSONObj::LargeSizeTrait>(); + ASSERT_GT(request.body.objsize(), BSONObjMaxInternalSize); + auto requestMsg = request.serialize(); + + Message replyMsg; + ASSERT(conn->call(requestMsg, replyMsg)); + + auto reply = OpMsg::parse(replyMsg); + auto replyStatus = getStatusFromCommandResult(reply.body); + ASSERT_NOT_OK(replyStatus); + ASSERT_EQ(replyStatus, ErrorCodes::BSONObjectTooLarge); +} } // namespace mongo |