summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/core/type4.js42
-rw-r--r--src/mongo/scripting/mozjs/bson.cpp8
-rw-r--r--src/mongo/scripting/mozjs/bson.h1
-rw-r--r--src/mongo/scripting/mozjs/cursor.cpp6
-rw-r--r--src/mongo/scripting/mozjs/cursor.h1
-rw-r--r--src/mongo/scripting/mozjs/cursor_handle.cpp6
-rw-r--r--src/mongo/scripting/mozjs/cursor_handle.h1
-rw-r--r--src/mongo/scripting/mozjs/mongo.cpp6
-rw-r--r--src/mongo/scripting/mozjs/nativefunction.cpp14
-rw-r--r--src/mongo/scripting/mozjs/nativefunction.h1
-rw-r--r--src/mongo/scripting/mozjs/wraptype.h22
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(