diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2016-03-14 10:46:07 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2016-03-14 16:22:01 -0400 |
commit | 3a29ba32703e1b10cf4aa3d48a7f05f1a76481ca (patch) | |
tree | 93916db11c2ca2c532effcf830810dd730f9d05a | |
parent | 0c25cd64ed475dbc88008af3c076cf2f235ce8d5 (diff) | |
download | mongo-3a29ba32703e1b10cf4aa3d48a7f05f1a76481ca.tar.gz |
SERVER-23119 Assert setShardVersion never uses invalid namespace
Ensure that setShardVersion is not sent for inline M/R output and same for
count command with missing or invalid namespace.
-rw-r--r-- | jstests/core/counta.js | 13 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_count_cmd.cpp | 15 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_map_reduce_cmd.cpp | 38 | ||||
-rw-r--r-- | src/mongo/s/set_shard_version_request.cpp | 1 |
4 files changed, 37 insertions, 30 deletions
diff --git a/jstests/core/counta.js b/jstests/core/counta.js index c65df230c72..0762769a088 100644 --- a/jstests/core/counta.js +++ b/jstests/core/counta.js @@ -1,9 +1,11 @@ // Check that count returns 0 in some exception cases. +(function() { +'use strict'; -t = db.jstests_counta; +var t = db.jstests_counta; t.drop(); -for (i = 0; i < 10; ++i) { +for (var i = 0; i < 10; ++i) { t.save({a: i}); } @@ -21,6 +23,7 @@ assert.throws(function() { }); // count must return error if collection name is absent -res = db.runCommand("count"); -assert.eq(res.ok, 0); // must not be OK -assert(res.code == 2); // should fail with errorcode("BadValue"), not an massert +var res = assert.commandFailed(db.runCommand("count")); +assert.eq(ErrorCodes.InvalidNamespace, res.code); + +})(); diff --git a/src/mongo/s/commands/cluster_count_cmd.cpp b/src/mongo/s/commands/cluster_count_cmd.cpp index 3ecd589451a..4fc8fea39e7 100644 --- a/src/mongo/s/commands/cluster_count_cmd.cpp +++ b/src/mongo/s/commands/cluster_count_cmd.cpp @@ -100,6 +100,10 @@ public: int options, std::string& errmsg, BSONObjBuilder& result) { + const NamespaceString nss(parseNs(dbname, cmdObj)); + uassert( + ErrorCodes::InvalidNamespace, "count command requires valid namespace", nss.isValid()); + long long skip = 0; if (cmdObj["skip"].isNumber()) { @@ -113,11 +117,8 @@ public: return false; } - const string collection = cmdObj.firstElement().valuestrsafe(); - const string fullns = dbname + "." + collection; - BSONObjBuilder countCmdBuilder; - countCmdBuilder.append("count", collection); + countCmdBuilder.append("count", nss.coll()); BSONObj filter; if (cmdObj["query"].isABSONObj()) { @@ -152,7 +153,7 @@ public: vector<Strategy::CommandResult> countResult; Strategy::commandOp( - txn, dbname, countCmdBuilder.done(), options, fullns, filter, &countResult); + txn, dbname, countCmdBuilder.done(), options, nss.ns(), filter, &countResult); long long total = 0; BSONObjBuilder shardSubTotal(result.subobjStart("shards")); @@ -196,7 +197,7 @@ public: ExplainCommon::Verbosity verbosity, const rpc::ServerSelectionMetadata& serverSelectionMetadata, BSONObjBuilder* out) const { - const string fullns = parseNs(dbname, cmdObj); + const NamespaceString nss(parseNs(dbname, cmdObj)); // Extract the targeting query. BSONObj targetingQuery; @@ -214,7 +215,7 @@ public: vector<Strategy::CommandResult> shardResults; Strategy::commandOp( - txn, dbname, explainCmdBob.obj(), options, fullns, targetingQuery, &shardResults); + txn, dbname, explainCmdBob.obj(), options, nss.ns(), targetingQuery, &shardResults); long long millisElapsed = timer.millis(); diff --git a/src/mongo/s/commands/cluster_map_reduce_cmd.cpp b/src/mongo/s/commands/cluster_map_reduce_cmd.cpp index 0efd5353366..507ea29f3bd 100644 --- a/src/mongo/s/commands/cluster_map_reduce_cmd.cpp +++ b/src/mongo/s/commands/cluster_map_reduce_cmd.cpp @@ -190,8 +190,7 @@ public: const string fullns = dbname + "." + collection; const string shardResultCollection = getTmpName(collection); - BSONObj customOut; - string finalColShort; + bool shardedOutput = false; string finalColLong; bool customOutDB = false; @@ -200,17 +199,26 @@ public: BSONElement outElmt = cmdObj.getField("out"); if (outElmt.type() == Object) { // Check if there is a custom output - BSONObj out = outElmt.embeddedObject(); - customOut = out; - - // Mode must be 1st element - finalColShort = out.firstElement().str(); - if (customOut.hasField("db")) { - customOutDB = true; - outDB = customOut.getField("db").str(); - } + BSONObj customOut = outElmt.embeddedObject(); + shardedOutput = customOut.getBoolField("sharded"); + + if (customOut.hasField("inline")) { + uassert(ErrorCodes::InvalidOptions, + "cannot specify inline and sharded output at the same time", + !shardedOutput); + uassert(ErrorCodes::InvalidOptions, + "cannot specify inline and output database at the same time", + !customOut.hasField("db")); + } else { + // Mode must be 1st element + const string finalColShort = customOut.firstElement().str(); + if (customOut.hasField("db")) { + customOutDB = true; + outDB = customOut.getField("db").str(); + } - finalColLong = outDB + "." + finalColShort; + finalColLong = outDB + "." + finalColShort; + } } // Ensure the input database exists @@ -231,7 +239,6 @@ public: const bool shardedInput = confIn && confIn->isShardingEnabled() && confIn->isSharded(fullns); - const bool shardedOutput = customOut.getBoolField("sharded"); if (!shardedOutput) { uassert(15920, @@ -255,11 +262,6 @@ public: invariant(maxChunkSizeBytes < std::numeric_limits<int>::max()); } - if (customOut.hasField("inline") && shardedOutput) { - errmsg = "cannot specify inline and sharded output at the same time"; - return false; - } - // modify command to run on shards with output to tmp collection string badShardedField; BSONObj shardedCommand = diff --git a/src/mongo/s/set_shard_version_request.cpp b/src/mongo/s/set_shard_version_request.cpp index 3a042d53850..f6afef3b4e4 100644 --- a/src/mongo/s/set_shard_version_request.cpp +++ b/src/mongo/s/set_shard_version_request.cpp @@ -99,6 +99,7 @@ SetShardVersionRequest SetShardVersionRequest::makeForVersioning( const NamespaceString& nss, const ChunkVersion& nssVersion, bool isAuthoritative) { + invariant(nss.isValid()); return SetShardVersionRequest( configServer, shardName, shardConnectionString, nss, nssVersion, isAuthoritative); } |