summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/apply_ops.cpp
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2014-09-24 15:08:54 -0400
committerBenety Goh <benety@mongodb.com>2014-09-25 11:15:45 -0400
commit05c6ae595922a89b96eb05db229cf02efae2ff89 (patch)
tree276088ecddc178a54b3a0956dfa7d3ec7bd41cae /src/mongo/db/commands/apply_ops.cpp
parentf23e92530e7356fa1959aac0f15cac526e46109f (diff)
downloadmongo-05c6ae595922a89b96eb05db229cf02efae2ff89.tar.gz
SERVER-15394 improve applyOps validation
Diffstat (limited to 'src/mongo/db/commands/apply_ops.cpp')
-rw-r--r--src/mongo/db/commands/apply_ops.cpp61
1 files changed, 56 insertions, 5 deletions
diff --git a/src/mongo/db/commands/apply_ops.cpp b/src/mongo/db/commands/apply_ops.cpp
index 947b57b2df0..c0a1f398e56 100644
--- a/src/mongo/db/commands/apply_ops.cpp
+++ b/src/mongo/db/commands/apply_ops.cpp
@@ -74,11 +74,9 @@ namespace mongo {
BSONObjIterator i( ops );
while ( i.more() ) {
BSONElement e = i.next();
- if ( e.type() == Object )
- continue;
- errmsg = "op not an object: ";
- errmsg += e.fieldName();
- return false;
+ if (!_checkOperation(e, errmsg)) {
+ return false;
+ }
}
}
@@ -122,6 +120,10 @@ namespace mongo {
BSONElement e = i.next();
const BSONObj& temp = e.Obj();
+ // Ignore 'n' operations.
+ const char *opType = temp["op"].valuestrsafe();
+ if (*opType == 'n') continue;
+
string ns = temp["ns"].String();
// Run operations under a nested lock as a hack to prevent them from yielding.
@@ -189,6 +191,55 @@ namespace mongo {
return true;
}
+
+ private:
+ /**
+ * Returns true if 'e' contains a valid operation.
+ */
+ bool _checkOperation(const BSONElement& e, string& errmsg) {
+ if (e.type() != Object) {
+ errmsg = str::stream() << "op not an object: " << e.fieldName();
+ return false;
+ }
+ BSONObj obj = e.Obj();
+ // op - operation type
+ BSONElement opElement = obj.getField("op");
+ if (opElement.eoo()) {
+ errmsg = str::stream() << "op does not contain required \"op\" field: "
+ << e.fieldName();
+ return false;
+ }
+ if (opElement.type() != mongo::String) {
+ errmsg = str::stream() << "\"op\" field is not a string: " << e.fieldName();
+ return false;
+ }
+ // operation type -- see logOp() comments for types
+ const char *opType = opElement.valuestrsafe();
+ if (*opType == '\0') {
+ errmsg = str::stream() << "\"op\" field value cannot be empty: " << e.fieldName();
+ return false;
+ }
+
+ // ns - namespace
+ // Only operations of type 'n' are allowed to have an empty namespace.
+ BSONElement nsElement = obj.getField("ns");
+ if (nsElement.eoo()) {
+ errmsg = str::stream() << "op does not contain required \"ns\" field: "
+ << e.fieldName();
+ return false;
+ }
+ if (nsElement.type() != mongo::String) {
+ errmsg = str::stream() << "\"ns\" field is not a string: " << e.fieldName();
+ return false;
+ }
+ if (*opType != 'n' && nsElement.String().empty()) {
+ errmsg = str::stream()
+ << "\"ns\" field value cannot be empty when op type is not 'n': "
+ << e.fieldName();
+ return false;
+ }
+ return true;
+ }
} applyOpsCmd;
}