summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2016-03-14 10:46:07 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2016-03-14 16:22:01 -0400
commit3a29ba32703e1b10cf4aa3d48a7f05f1a76481ca (patch)
tree93916db11c2ca2c532effcf830810dd730f9d05a
parent0c25cd64ed475dbc88008af3c076cf2f235ce8d5 (diff)
downloadmongo-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.js13
-rw-r--r--src/mongo/s/commands/cluster_count_cmd.cpp15
-rw-r--r--src/mongo/s/commands/cluster_map_reduce_cmd.cpp38
-rw-r--r--src/mongo/s/set_shard_version_request.cpp1
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);
}