summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Reams <jbreams@mongodb.com>2019-08-07 11:08:12 -0400
committerJonathan Reams <jbreams@mongodb.com>2019-08-07 13:42:11 -0400
commite2de2b23e821614a8c3117fa8650b910f44c7638 (patch)
treee25d0513fc38c86ef5d173ca83420315e357bbf2
parent14f4a2d1973b4a7056ceeefc8814c62d0f12c33d (diff)
downloadmongo-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.cpp9
-rw-r--r--src/mongo/bson/bsonobj.h6
-rw-r--r--src/mongo/rpc/op_msg_integration_test.cpp29
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