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:42:11 -0400 |
commit | e2de2b23e821614a8c3117fa8650b910f44c7638 (patch) | |
tree | e25d0513fc38c86ef5d173ca83420315e357bbf2 | |
parent | 14f4a2d1973b4a7056ceeefc8814c62d0f12c33d (diff) | |
download | mongo-e2de2b23e821614a8c3117fa8650b910f44c7638.tar.gz |
SERVER-42657 Make DataType<BSONObj> noexcept safer4.2.0-rc8
(cherry picked from commit d7455e67f5b002de110f7972603906888aff66b8)
-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 7b5439cd40a..a0628fa9c3c 100644 --- a/src/mongo/bson/bsonobj.cpp +++ b/src/mongo/bson/bsonobj.cpp @@ -618,8 +618,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() @@ -636,6 +639,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 86f858258ad..5f50271e4c7 100644 --- a/src/mongo/bson/bsonobj.h +++ b/src/mongo/bson/bsonobj.h @@ -826,7 +826,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) { @@ -836,13 +836,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 |