summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVesselina Ratcheva <vesselina.ratcheva@10gen.com>2022-12-05 17:18:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-01-23 00:27:20 +0000
commitc585f971a68e707da7420a6a5c19988bb65a6205 (patch)
tree28e0c798339c0c0095188ff6b781b526592fb21b
parent053c745ed3de8faa32f8b24fc1780a7521af932b (diff)
downloadmongo-c585f971a68e707da7420a6a5c19988bb65a6205.tar.gz
SERVER-70360 Set upper limit on wtimeout
(cherry picked from commit 85aa2d8d807d5472b1274971afc43f4c6ecd6923)
-rw-r--r--etc/backports_required_for_multiversion_tests.yml4
-rw-r--r--jstests/replsets/wtimeout_too_large.js32
-rw-r--r--jstests/sharding/replication_with_undefined_shard_key.js4
-rw-r--r--src/mongo/db/write_concern_options.cpp9
-rw-r--r--src/mongo/db/write_concern_options_test.cpp10
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) {