From 83328dadb7aba72fc9202c91d5715ab4a2d04fcb Mon Sep 17 00:00:00 2001 From: Louis Williams Date: Fri, 26 Oct 2018 12:06:36 -0400 Subject: [PATCH] SERVER-37749 replSetResizeOplog command does not validate argument correctly --- .../noPassthrough/repl_set_resize_oplog.js | 47 +++++++++++++++++++ src/mongo/db/commands/resize_oplog.cpp | 10 +++- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 jstests/noPassthrough/repl_set_resize_oplog.js diff --git a/jstests/noPassthrough/repl_set_resize_oplog.js b/jstests/noPassthrough/repl_set_resize_oplog.js new file mode 100644 index 00000000000..23682467f9d --- /dev/null +++ b/jstests/noPassthrough/repl_set_resize_oplog.js @@ -0,0 +1,47 @@ +/** + * Tests that resizing the oplog works as expected and validates input arguments. + * + * @tags: [requires_replication, requires_wiredtiger] + */ +(function() { + "use strict"; + + let replSet = new ReplSetTest({nodes: 2, oplogSize: 50}); + replSet.startSet(); + replSet.initiate(); + + let primary = replSet.getPrimary(); + + const MB = 1024 * 1024; + const GB = 1024 * MB; + const PB = 1024 * GB; + const EB = 1024 * PB; + + assert.eq(primary.getDB('local').oplog.rs.stats().maxSize, 50 * MB); + + // Too small: 990MB + assert.commandFailedWithCode( + primary.getDB('admin').runCommand({replSetResizeOplog: 1, size: 900}), + ErrorCodes.InvalidOptions, + "Expected replSetResizeOplog to fail because the size was too small"); + + // Way too small: -1GB + assert.commandFailedWithCode( + primary.getDB('admin').runCommand({replSetResizeOplog: 1, size: -1 * GB / MB}), + ErrorCodes.InvalidOptions, + "Expected replSetResizeOplog to fail because the size was too small"); + + // Too big: 8EB + assert.commandFailedWithCode( + primary.getDB('admin').runCommand({replSetResizeOplog: 1, size: 8 * EB / MB}), + ErrorCodes.InvalidOptions, + "Expected replSetResizeOplog to fail because the size was too big"); + + // The maximum: 1PB + assert.commandWorked( + primary.getDB('admin').runCommand({replSetResizeOplog: 1, size: 1 * PB / MB})); + + assert.eq(primary.getDB('local').oplog.rs.stats().maxSize, 1 * PB); + + replSet.stopSet(); +})(); diff --git a/src/mongo/db/commands/resize_oplog.cpp b/src/mongo/db/commands/resize_oplog.cpp index 35d230459bc..95abdb5677d 100644 --- a/src/mongo/db/commands/resize_oplog.cpp +++ b/src/mongo/db/commands/resize_oplog.cpp @@ -1,4 +1,3 @@ - /** * Copyright (C) 2018-present MongoDB, Inc. * @@ -101,10 +100,17 @@ public: } long long sizeMb = jsobj["size"].numberLong(); - long long size = sizeMb * 1024 * 1024; if (sizeMb < 990L) { uasserted(ErrorCodes::InvalidOptions, "oplog size should be 990MB at least"); } + + const long long kMB = 1024 * 1024; + const long long kPB = kMB * 1024 * 1024 * 1024; + if (sizeMb > kPB / kMB) { + uasserted(ErrorCodes::InvalidOptions, "oplog size in MB cannot exceed maximum of 1PB"); + } + long long size = sizeMb * kMB; + WriteUnitOfWork wunit(opCtx); Status status = coll->getRecordStore()->updateCappedSize(opCtx, size); uassertStatusOK(status);