Skip to content

Commit

Permalink
SERVER-17387 prevent invalid projections from causing findAndModify t…
Browse files Browse the repository at this point in the history
…o trigger a logOp() rollback
  • Loading branch information
dstorch committed Mar 9, 2015
1 parent e8f722a commit 98276a1
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 9 deletions.
66 changes: 64 additions & 2 deletions jstests/core/find_and_modify.js
Expand Up @@ -45,9 +45,71 @@ assert.throws(function() { t.findAndModify({query:{x:1}, update:{y:2}, remove:tr
assert.throws(function() { t.findAndModify({query:{x:1}, update:{y:2}, new:true, remove:true}); });
assert.throws(function() { t.findAndModify({query:{x:1}, upsert:true, remove:true}); });

// SERVER-17372
//
// SERVER-17387: Find and modify should throw in the case of invalid projection.
//

t.drop();

// Insert case.
var cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "miss"},
update: {$inc: {y: 1}},
fields: {foo: {$pop: ["bar"]}},
upsert: true,
new: true
});
assert.commandFailed(cmdRes);

t.insert({_id: "found"});

// Update with upsert + new.
cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "found"},
update: {$inc: {y: 1}},
fields: {foo: {$pop: ["bar"]}},
upsert: true,
new: true
});
assert.commandFailed(cmdRes);

// Update with just new: true.
cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "found"},
update: {$inc: {y: 1}},
fields: {foo: {$pop: ["bar"]}},
new: true
});
assert.commandFailed(cmdRes);

// Update with just upsert: true.
cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "found"},
update: {$inc: {y: 1}},
fields: {foo: {$pop: ["bar"]}},
upsert: true
});
assert.commandFailed(cmdRes);

// Update with neither upsert nor new flags.
cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "found"},
update: {$inc: {y: 1}},
fields: {foo: {$pop: ["bar"]}},
});
assert.commandFailed(cmdRes);

//
// SERVER-17372
//

t.drop();
cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "miss"},
update: {$inc: {y: 1}},
Expand All @@ -57,7 +119,7 @@ assert.commandWorked(cmdRes);
assert("value" in cmdRes);
assert.eq(null, cmdRes.value);

var cmdRes = db.runCommand({
cmdRes = db.runCommand({
findAndModify: t.getName(),
query: {_id: "missagain"},
update: {$inc: {y: 1}},
Expand Down
25 changes: 18 additions & 7 deletions src/mongo/db/commands/find_and_modify.cpp
Expand Up @@ -372,6 +372,14 @@ namespace mongo {
if ( found ) {
deleteObjects(txn, ctx.db(), ns, queryModified, PlanExecutor::YIELD_MANUAL,
true, true);

// Committing the WUOW can close the current snapshot. Until this happens, the
// snapshot id should not have changed.
invariant(txn->recoveryUnit()->getSnapshotId() == snapshotDoc.snapshotId());

// Must commit the write before doing anything that could throw.
wuow.commit();

BSONObjBuilder le( result.subobjStart( "lastErrorObject" ) );
le.appendNumber( "n" , 1 );
le.done();
Expand Down Expand Up @@ -424,6 +432,9 @@ namespace mongo {
// for some BSON manipulation).
repl::logOp(txn, "i", collection->ns().ns().c_str(), newDoc);

// Must commit the write and logOp() before doing anything that could throw.
wuow.commit();

// The third argument indicates whether or not we have something for the
// 'value' field returned by a findAndModify command.
//
Expand Down Expand Up @@ -470,6 +481,13 @@ namespace mongo {
invariant(res.existing);
LOG(3) << "update result: " << res;

// Committing the WUOW can close the current snapshot. Until this happens, the
// snapshot id should not have changed.
invariant(txn->recoveryUnit()->getSnapshotId() == snapshotDoc.snapshotId());

// Must commit the write before doing anything that could throw.
wuow.commit();

if (returnNew) {
dassert(!res.newObj.isEmpty());
_appendHelper(result, res.newObj, true, fields, whereCallback);
Expand All @@ -485,13 +503,6 @@ namespace mongo {
}
}

// Committing the WUOW can close the current snapshot. Until this happens, the
// snapshot id should not have changed.
if (found) {
invariant(txn->recoveryUnit()->getSnapshotId() == snapshotDoc.snapshotId());
}
wuow.commit();

return true;
}

Expand Down

0 comments on commit 98276a1

Please sign in to comment.