diff options
author | matt dannenberg <matt.dannenberg@10gen.com> | 2013-07-29 16:27:09 -0400 |
---|---|---|
committer | matt dannenberg <matt.dannenberg@10gen.com> | 2013-08-09 17:48:46 -0400 |
commit | cd81198d0280abc8144bd7fa291a15564c1c0ae4 (patch) | |
tree | 83ddb514572d6183a05bc47f5ed4c2804372e135 | |
parent | af6828e05aaea88e181cad598cc1274e2838d25a (diff) | |
download | mongo-cd81198d0280abc8144bd7fa291a15564c1c0ae4.tar.gz |
SERVER-5782 $literal operator to help prevent injection attacks
-rw-r--r-- | jstests/aggregation/bugs/server5782.js | 18 | ||||
-rw-r--r-- | jstests/aggregation/testshard1.js | 9 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 3 |
3 files changed, 29 insertions, 1 deletions
diff --git a/jstests/aggregation/bugs/server5782.js b/jstests/aggregation/bugs/server5782.js new file mode 100644 index 00000000000..d4ac2eeb6f1 --- /dev/null +++ b/jstests/aggregation/bugs/server5782.js @@ -0,0 +1,18 @@ +load('jstests/aggregation/extras/utils.js'); + +db.server5782.drop(); +db.server5782.save({string: "foo"}); + +// check that without $literal we end up comparing a field with itself and the result is true +var result = db.runCommand({aggregate: "server5782", + pipeline:[{$project: + {stringis$string: {$eq:["$string", '$string']}} + }]}); +assert.eq(result.result[0].stringis$string, true); + +// check that with $literal we end up comparing a field with '$string' and the result is true +var result = db.runCommand({aggregate: "server5782", + pipeline:[{$project: + {stringis$string: {$eq:["$string", {$literal:'$string'}]}} + }]}); +assert.eq(result.result[0].stringis$string, false); diff --git a/jstests/aggregation/testshard1.js b/jstests/aggregation/testshard1.js index 864f58db375..66dd8b261dc 100644 --- a/jstests/aggregation/testshard1.js +++ b/jstests/aggregation/testshard1.js @@ -24,8 +24,10 @@ db = shardedAggTest.getDB( "aggShard" ); /* make sure its cleaned up */ db.ts1.drop(); +db.literal.drop(); shardedAggTest.adminCommand( { shardcollection : "aggShard.ts1", key : { "_id" : 1 } } ); +shardedAggTest.adminCommand( { shardcollection : "aggShard.literal", key : { "_id" : 1 } } ); /* @@ -203,5 +205,12 @@ assert.eq(db.ts1.find().sort({_id:1}).toArray(), // Make sure we error out if $out collection is sharded assertErrorCode(db.outCollection, [{$out: db.ts1.getName()}], 17017); +db.literal.save({dollar:false}); + +result = db.literal.aggregate( + {$project:{_id:0, cost:{$cond:['$dollar', {$literal:'$1.00'}, {$literal:'$.99'}]}}}); + +assert.eq([{cost:'$.99'}], result.result); + // shut everything down shardedAggTest.stop(); diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index d121b99c4e0..bb3589b66e5 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -273,6 +273,7 @@ namespace mongo { {"$hour", ExpressionHour::create, OpDesc::FIXED_COUNT, 1}, {"$ifNull", ExpressionIfNull::create, OpDesc::FIXED_COUNT, 2}, // $let handled specially in parseExpression + // $literal handled specially in parseExpression // $map handled specially in parseExpression {"$lt", ExpressionCompare::createLt, OpDesc::FIXED_COUNT, 2}, {"$lte", ExpressionCompare::createLte, OpDesc::FIXED_COUNT, 2}, @@ -306,7 +307,7 @@ namespace mongo { /* look for the specified operator */ const char* opName = exprElement.fieldName(); - if (str::equals(opName, "$const")) { + if (str::equals(opName, "$const") || str::equals(opName, "$literal")) { return ExpressionConstant::createFromBsonElement(&exprElement); } else if (str::equals(opName, "$let")) { |