diff options
-rw-r--r-- | jstests/core/type4.js | 42 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/bson.cpp | 8 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/bson.h | 1 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/cursor.cpp | 6 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/cursor.h | 1 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/cursor_handle.cpp | 6 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/cursor_handle.h | 1 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/mongo.cpp | 6 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/nativefunction.cpp | 14 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/nativefunction.h | 1 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/wraptype.h | 22 |
11 files changed, 75 insertions, 33 deletions
diff --git a/jstests/core/type4.js b/jstests/core/type4.js new file mode 100644 index 00000000000..c35d7baecca --- /dev/null +++ b/jstests/core/type4.js @@ -0,0 +1,42 @@ +(function(){ + "use strict"; + + // Tests for SERVER-20080 + // + // Verify that various types cannot be invoked as constructors + + var t = db.jstests_type4; + t.drop(); + t.insert({}); + t.insert({}); + t.insert({}); + + var oldReadMode = db.getMongo()._readMode; + + assert.throws(function(){ + (new _rand())(); + }, [], "invoke constructor on natively injected function"); + + assert.throws(function(){ + var doc = db.test.findOne(); + new doc(); + }, [], "invoke constructor on BSON"); + + assert.throws(function(){ + db.getMongo()._readMode = "commands"; + var cursor = t.find(); + cursor.next(); + + new cursor._cursor._cursorHandle(); + }, [], "invoke constructor on CursorHandle"); + + assert.throws(function(){ + db.getMongo()._readMode = "compatibility"; + var cursor = t.find(); + cursor.next(); + + new cursor._cursor(); + }, [], "invoke constructor on Cursor"); + + db.getMongo()._readMode = oldReadMode; +})(); diff --git a/src/mongo/scripting/mozjs/bson.cpp b/src/mongo/scripting/mozjs/bson.cpp index 308e29d90f3..9c972a6b3fc 100644 --- a/src/mongo/scripting/mozjs/bson.cpp +++ b/src/mongo/scripting/mozjs/bson.cpp @@ -75,7 +75,7 @@ BSONHolder* getHolder(JSObject* obj) { void BSONInfo::make(JSContext* cx, JS::MutableHandleObject obj, BSONObj bson, bool ro) { auto scope = getScope(cx); - scope->getBsonProto().newInstance(obj); + scope->getBsonProto().newObject(obj); JS_SetPrivate(obj, new BSONHolder(bson, ro)); } @@ -193,12 +193,6 @@ void BSONInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, boo } } -void BSONInfo::construct(JSContext* cx, JS::CallArgs args) { - auto scope = getScope(cx); - - scope->getBsonProto().newObject(args.rval()); -} - std::tuple<BSONObj*, bool> BSONInfo::originalBSON(JSContext* cx, JS::HandleObject obj) { std::tuple<BSONObj*, bool> out(nullptr, false); diff --git a/src/mongo/scripting/mozjs/bson.h b/src/mongo/scripting/mozjs/bson.h index bcf57b5eda4..3b150801793 100644 --- a/src/mongo/scripting/mozjs/bson.h +++ b/src/mongo/scripting/mozjs/bson.h @@ -47,7 +47,6 @@ namespace mozjs { * ::make() from C++. */ struct BSONInfo : public BaseInfo { - static void construct(JSContext* cx, JS::CallArgs args); static void delProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* succeeded); static void enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties); static void finalize(JSFreeOp* fop, JSObject* obj); diff --git a/src/mongo/scripting/mozjs/cursor.cpp b/src/mongo/scripting/mozjs/cursor.cpp index 8f6bb7b540c..8660287a13a 100644 --- a/src/mongo/scripting/mozjs/cursor.cpp +++ b/src/mongo/scripting/mozjs/cursor.cpp @@ -68,12 +68,6 @@ void CursorInfo::finalize(JSFreeOp* fop, JSObject* obj) { } } -void CursorInfo::construct(JSContext* cx, JS::CallArgs args) { - auto scope = getScope(cx); - - scope->getCursorProto().newObject(args.rval()); -} - void CursorInfo::Functions::next(JSContext* cx, JS::CallArgs args) { auto cursor = getCursor(args); diff --git a/src/mongo/scripting/mozjs/cursor.h b/src/mongo/scripting/mozjs/cursor.h index 39c8ba56295..87bd8e1de80 100644 --- a/src/mongo/scripting/mozjs/cursor.h +++ b/src/mongo/scripting/mozjs/cursor.h @@ -42,7 +42,6 @@ namespace mozjs { * from C++. Current callers are all via the Mongo object. */ struct CursorInfo : public BaseInfo { - static void construct(JSContext* cx, JS::CallArgs args); static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { diff --git a/src/mongo/scripting/mozjs/cursor_handle.cpp b/src/mongo/scripting/mozjs/cursor_handle.cpp index 597ebe2ccd6..fcdc3dd525b 100644 --- a/src/mongo/scripting/mozjs/cursor_handle.cpp +++ b/src/mongo/scripting/mozjs/cursor_handle.cpp @@ -84,12 +84,6 @@ void CursorHandleInfo::finalize(JSFreeOp* fop, JSObject* obj) { } } -void CursorHandleInfo::construct(JSContext* cx, JS::CallArgs args) { - auto scope = getScope(cx); - - scope->getCursorHandleProto().newObject(args.rval()); -} - void CursorHandleInfo::Functions::zeroCursorId(JSContext* cx, JS::CallArgs args) { long long* cursorId = getCursorId(args); if (cursorId) { diff --git a/src/mongo/scripting/mozjs/cursor_handle.h b/src/mongo/scripting/mozjs/cursor_handle.h index 95f00a3d964..792b382ae5e 100644 --- a/src/mongo/scripting/mozjs/cursor_handle.h +++ b/src/mongo/scripting/mozjs/cursor_handle.h @@ -42,7 +42,6 @@ namespace mozjs { * callers are all via the Mongo object. */ struct CursorHandleInfo : public BaseInfo { - static void construct(JSContext* cx, JS::CallArgs args); static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { diff --git a/src/mongo/scripting/mozjs/mongo.cpp b/src/mongo/scripting/mozjs/mongo.cpp index 3a37fe5d442..2f1b41e91cd 100644 --- a/src/mongo/scripting/mozjs/mongo.cpp +++ b/src/mongo/scripting/mozjs/mongo.cpp @@ -213,7 +213,7 @@ void MongoBase::Functions::find(JSContext* cx, JS::CallArgs args) { } JS::RootedObject c(cx); - scope->getCursorProto().newInstance(&c); + scope->getCursorProto().newObject(&c); setCursor(c, std::move(cursor), args); @@ -405,7 +405,7 @@ void MongoBase::Functions::cursorFromId(JSContext* cx, JS::CallArgs args) { cursor->setBatchSize(ValueWriter(cx, args.get(2)).toInt32()); JS::RootedObject c(cx); - scope->getCursorProto().newInstance(&c); + scope->getCursorProto().newObject(&c); setCursor(c, std::move(cursor), args); @@ -425,7 +425,7 @@ void MongoBase::Functions::cursorHandleFromId(JSContext* cx, JS::CallArgs args) long long cursorId = NumberLongInfo::ToNumberLong(cx, args.get(0)); JS::RootedObject c(cx); - scope->getCursorHandleProto().newInstance(&c); + scope->getCursorHandleProto().newObject(&c); setCursorHandle(c, cursorId, args); diff --git a/src/mongo/scripting/mozjs/nativefunction.cpp b/src/mongo/scripting/mozjs/nativefunction.cpp index 010b6a13587..5ffdc5f902d 100644 --- a/src/mongo/scripting/mozjs/nativefunction.cpp +++ b/src/mongo/scripting/mozjs/nativefunction.cpp @@ -67,15 +67,15 @@ NativeHolder* getHolder(JS::CallArgs args) { } // namespace -void NativeFunctionInfo::construct(JSContext* cx, JS::CallArgs args) { - auto scope = getScope(cx); - - scope->getNativeFunctionProto().newObject(args.rval()); -} - void NativeFunctionInfo::call(JSContext* cx, JS::CallArgs args) { auto holder = getHolder(args); + if (! holder) { + // Calling the prototype + args.rval().setUndefined(); + return; + } + BSONObjBuilder bob; for (unsigned i = 0; i < args.length(); i++) { @@ -115,7 +115,7 @@ void NativeFunctionInfo::make(JSContext* cx, void* data) { auto scope = getScope(cx); - scope->getNativeFunctionProto().newInstance(obj); + scope->getNativeFunctionProto().newObject(obj); JS_SetPrivate(obj, new NativeHolder(function, data)); } diff --git a/src/mongo/scripting/mozjs/nativefunction.h b/src/mongo/scripting/mozjs/nativefunction.h index 0467b2c4743..6a676a180cf 100644 --- a/src/mongo/scripting/mozjs/nativefunction.h +++ b/src/mongo/scripting/mozjs/nativefunction.h @@ -48,7 +48,6 @@ namespace mozjs { * in JS via ::make() from C++. */ struct NativeFunctionInfo : public BaseInfo { - static void construct(JSContext* cx, JS::CallArgs args); static void call(JSContext* cx, JS::CallArgs args); static void finalize(JSFreeOp* fop, JSObject* obj); diff --git a/src/mongo/scripting/mozjs/wraptype.h b/src/mongo/scripting/mozjs/wraptype.h index c5ca6095e76..7b45e24e13e 100644 --- a/src/mongo/scripting/mozjs/wraptype.h +++ b/src/mongo/scripting/mozjs/wraptype.h @@ -280,22 +280,30 @@ public: * newInstance calls the constructor, a la new Type() in js */ void newInstance(JS::MutableHandleObject out) { + dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + JS::AutoValueVector args(_context); newInstance(args, out); } void newInstance(const JS::HandleValueArray& args, JS::MutableHandleObject out) { + dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + out.set(_assertPtr(JS_New(_context, _proto, args))); } void newInstance(JS::MutableHandleValue out) { + dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + JS::AutoValueVector args(_context); newInstance(args, out); } void newInstance(const JS::HandleValueArray& args, JS::MutableHandleValue out) { + dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + out.setObjectOrNull(_assertPtr(JS_New(_context, _proto, args))); } @@ -349,6 +357,8 @@ private: // Use this if you want your types installed, but not visible in the // global scope void _installPrivate(JS::HandleObject global) { + dassert(T::construct == BaseInfo::construct); + JS::RootedObject parent(_context); _inheritFrom(T::inheritFrom, global, &parent); @@ -370,6 +380,18 @@ private: // Use this to attach things to types that we don't provide like // Object, or Array void _installOverNative(JS::HandleObject global) { + dassert(T::addProperty == BaseInfo::addProperty); + dassert(T::call == BaseInfo::call); + dassert(T::construct == BaseInfo::construct); + dassert(T::convert == BaseInfo::convert); + dassert(T::delProperty == BaseInfo::delProperty); + dassert(T::enumerate == BaseInfo::enumerate); + dassert(T::finalize == BaseInfo::finalize); + dassert(T::getProperty == BaseInfo::getProperty); + dassert(T::hasInstance == BaseInfo::hasInstance); + dassert(T::resolve == BaseInfo::resolve); + dassert(T::setProperty == BaseInfo::setProperty); + JS::RootedValue value(_context); if (!JS_GetProperty(_context, global, T::className, &value)) throwCurrentJSException( |