Skip to content

Commit

Permalink
SERVER-9878 Add type checks to V8 C++ bindings
Browse files Browse the repository at this point in the history
The main focus of this ticket is tightening up input validation in
our V8 bindings. Doing this required normalizing the way we create
custom types in JS that have special C++-driven behavior. All special
types now use FunctionTemplates that are attached to the V8Scope object.
This allows us to test if an object is of the correct type before using
it.

Other related tickets partially addressed:
SERVER-8961 Differences in argument validation of custom types between v8 and Spidermonkey
SERVER-9803 Handle regular expression parse errors without seg faulting
  • Loading branch information
RedBeard0531 committed Jun 17, 2013
1 parent c676251 commit fda4a23
Show file tree
Hide file tree
Showing 7 changed files with 752 additions and 623 deletions.
12 changes: 5 additions & 7 deletions jstests/constructors.js
Expand Up @@ -91,31 +91,29 @@ function whereConstructorTest (constructorList) {

var dbrefConstructors = {
"valid" : [
// SERVER-8961
//"DBRef()",
"DBRef(\"namespace\", 0)",
"DBRef(\"namespace\", \"test\")",
"DBRef(\"namespace\", ObjectId())",
"DBRef(\"namespace\", ObjectId(\"000000000000000000000000\"))",
"DBRef(true, ObjectId())"
],
"invalid" : [
"DBRef()",
"DBRef(true, ObjectId())",
"DBRef(\"namespace\")",
"DBRef(\"namespace\", ObjectId(), true)"
]
}

var dbpointerConstructors = {
"valid" : [
// SERVER-8961
//"DBPointer(\"namespace\", 0)",
//"DBPointer(\"namespace\", \"test\")",
"DBPointer(\"namespace\", ObjectId())",
"DBPointer(\"namespace\", ObjectId(\"000000000000000000000000\"))",
"DBPointer(true, ObjectId())"
],
"invalid" : [
"DBPointer()",
"DBPointer(true, ObjectId())",
"DBPointer(\"namespace\", 0)",
"DBPointer(\"namespace\", \"test\")",
"DBPointer(\"namespace\")",
"DBPointer(\"namespace\", ObjectId(), true)"
]
Expand Down
22 changes: 22 additions & 0 deletions jstests/dbref3.js
@@ -0,0 +1,22 @@
// Make sure we only make a DBRef object for objects where the first field is a string named $ref
// and the second field is $id with any type. Only the first two fields matter for deciding if it
// is a DBRef. See http://docs.mongodb.org/manual/reference/database-references/#dbrefs.

var t = db.dbref3

// true cases
t.insert({sub: {$ref: "foo", $id: "bar"}, dbref: true});
t.insert({sub: {$ref: "foo", $id: "bar", $db: "baz"}, dbref: true});
t.insert({sub: {$ref: "foo", $id: "bar", db: "baz"}, dbref: true}); // out of spec but accepted
t.insert({sub: {$ref: "foo", $id: ObjectId()}, dbref: true});
t.insert({sub: {$ref: "foo", $id: 1}, dbref: true});

t.insert({sub: {$ref: 123/*not a string*/, $id: "bar"}, dbref: false});
t.insert({sub: {$id: "bar", $ref: "foo"}, dbref: false});
t.insert({sub: {$ref: "foo"}, dbref: false});
t.insert({sub: {$id: "foo"}, dbref: false});
t.insert({sub: {other: 1, $ref: "foo", $id: "bar"}, dbref: false});

t.find().forEach(function(obj) {
assert.eq(obj.sub.constructor == DBRef, obj.dbref, tojson(obj));
});
13 changes: 13 additions & 0 deletions src/mongo/dbtests/jstests.cpp
Expand Up @@ -439,6 +439,19 @@ namespace JSTests {
ASSERT_EQUALS( (string)"^a" , out["a"].regex() );
ASSERT_EQUALS( (string)"i" , out["a"].regexFlags() );

// This regex used to cause a segfault because x isn't a valid flag for a js RegExp.
// Now it throws a JS exception.
BSONObj invalidRegex = BSON_ARRAY(BSON("regex" << BSONRegEx("asdf", "x")));
const char* code = "function (obj) {"
" var threw = false;"
" try {"
" obj.regex;" // should throw
" } catch(e) {"
" threw = true;"
" }"
" assert(threw);"
"}";
ASSERT_EQUALS(s->invoke(code, &invalidRegex, NULL), 0);
}

// array
Expand Down

0 comments on commit fda4a23

Please sign in to comment.