diff options
author | Vesselina Ratcheva <vesselina.ratcheva@10gen.com> | 2022-12-05 17:18:41 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-01-23 00:27:20 +0000 |
commit | c585f971a68e707da7420a6a5c19988bb65a6205 (patch) | |
tree | 28e0c798339c0c0095188ff6b781b526592fb21b | |
parent | 053c745ed3de8faa32f8b24fc1780a7521af932b (diff) | |
download | mongo-c585f971a68e707da7420a6a5c19988bb65a6205.tar.gz |
SERVER-70360 Set upper limit on wtimeout
(cherry picked from commit 85aa2d8d807d5472b1274971afc43f4c6ecd6923)
-rw-r--r-- | etc/backports_required_for_multiversion_tests.yml | 4 | ||||
-rw-r--r-- | jstests/replsets/wtimeout_too_large.js | 32 | ||||
-rw-r--r-- | jstests/sharding/replication_with_undefined_shard_key.js | 4 | ||||
-rw-r--r-- | src/mongo/db/write_concern_options.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/write_concern_options_test.cpp | 10 |
5 files changed, 50 insertions, 9 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index 222f15921f9..6bffc5256f3 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -228,6 +228,8 @@ last-continuous: ticket: SERVER-70190 - test_file: jstests/core/cover_null_queries.js ticket: SERVER-70436 + - test_file: jstests/replsets/wtimeout_too_large.js + ticket: SERVER-70360 - test_file: jstests/sharding/all_collection_stats.js ticket: SERVER-71477 - test_file: jstests/sharding/drop_collection.js @@ -545,6 +547,8 @@ last-lts: ticket: SERVER-70190 - test_file: jstests/core/cover_null_queries.js ticket: SERVER-70436 + - test_file: jstests/replsets/wtimeout_too_large.js + ticket: SERVER-70360 - test_file: jstests/sharding/all_collection_stats.js ticket: SERVER-71477 - test_file: jstests/sharding/drop_collection.js diff --git a/jstests/replsets/wtimeout_too_large.js b/jstests/replsets/wtimeout_too_large.js new file mode 100644 index 00000000000..3beef1ed578 --- /dev/null +++ b/jstests/replsets/wtimeout_too_large.js @@ -0,0 +1,32 @@ +/** + * Test that the server rejects extremely large values for write concern wtimeout. + */ + +(function() { +"use strict"; + +const rst = new ReplSetTest({name: jsTestName(), nodes: 2}); +rst.startSet(); +rst.initiateWithHighElectionTimeout(); + +const dbName = "testdb"; +const collName = "testcoll"; + +const primary = rst.getPrimary(); +const primaryDB = primary.getDB(dbName); +const primaryColl = primaryDB.getCollection(collName); + +jsTestLog("Issuing a write within accepted wtimeout bounds"); +assert.commandWorked( + primaryColl.insert({a: 1}, {writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMS}})); + +jsTestLog("Issuing a high wtimeout write and confirming that it gets rejected"); + +// Outside int32 bounds. +const oneTrillionMS = 1000 * 1000 * 1000 * 1000; +assert.commandFailedWithCode( + primaryColl.insert({b: 2}, {writeConcern: {w: 2, wtimeout: oneTrillionMS}}), + ErrorCodes.FailedToParse); + +rst.stopSet(); +})(); diff --git a/jstests/sharding/replication_with_undefined_shard_key.js b/jstests/sharding/replication_with_undefined_shard_key.js index f684bd29e29..a363ff06b9e 100644 --- a/jstests/sharding/replication_with_undefined_shard_key.js +++ b/jstests/sharding/replication_with_undefined_shard_key.js @@ -22,9 +22,9 @@ jsTestLog("Doing writes that generate oplog entries including undefined document assert.commandWorked(mongosColl.update( {}, {$set: {a: 1}}, - {multi: true, writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMs}})); + {multi: true, writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMS}})); assert.commandWorked( - mongosColl.remove({}, {writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMs}})); + mongosColl.remove({}, {writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMS}})); st.stop(); })();
\ No newline at end of file diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp index c87e21691fc..7cf9b373d61 100644 --- a/src/mongo/db/write_concern_options.cpp +++ b/src/mongo/db/write_concern_options.cpp @@ -233,11 +233,18 @@ void serializeWriteConcernW(const WriteConcernW& w, StringData fieldName, BSONOb } std::int64_t parseWTimeoutFromBSON(BSONElement element) { + // Store wTimeout as a 64-bit value but functionally limit it to int32 as values larger than + // than that do not make much sense to use and were not previously supported. constexpr std::array<mongo::BSONType, 4> validTypes{ NumberLong, NumberInt, NumberDecimal, NumberDouble}; bool isValidType = std::any_of( validTypes.begin(), validTypes.end(), [&](auto type) { return element.type() == type; }); - return isValidType ? element.safeNumberLong() : 0; + + auto value = isValidType ? element.safeNumberLong() : 0; + uassert(ErrorCodes::FailedToParse, + "wtimeout must be a 32-bit integer", + value <= std::numeric_limits<int32_t>::max()); + return value; } BSONObj WriteConcernOptions::toBSON() const { diff --git a/src/mongo/db/write_concern_options_test.cpp b/src/mongo/db/write_concern_options_test.cpp index abce6fa331e..87560b185d1 100644 --- a/src/mongo/db/write_concern_options_test.cpp +++ b/src/mongo/db/write_concern_options_test.cpp @@ -150,14 +150,12 @@ TEST(WriteConcernOptionsTest, ParseWTimeoutAsNaNDouble) { ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout); } -TEST(WriteConcernOptionsTest, ParseWTimeoutAsDoubleLargerThanInt) { +TEST(WriteConcernOptionsTest, ParseWTimeoutAsDoubleLargerThanIntFails) { // Set wtimeout to a double with value larger than INT_MAX. auto sw = WriteConcernOptions::parse(BSON("wtimeout" << 2999999999.0)); - ASSERT_OK(sw.getStatus()); - WriteConcernOptions options = sw.getValue(); - ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode); - ASSERT_EQUALS(1, stdx::get<int64_t>(options.w)); - ASSERT_EQUALS(options.wTimeout, Milliseconds{2999999999}); + auto status = sw.getStatus(); + ASSERT_NOT_OK(status); + ASSERT_EQUALS(ErrorCodes::FailedToParse, status.code()); } TEST(WriteConcernOptionsTest, ParseReturnsFailedToParseOnUnknownField) { |