diff options
author | Waley Chen <waleycz@gmail.com> | 2016-08-02 11:53:25 -0400 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2017-05-04 13:33:01 -0400 |
commit | a9e694a18f25775764c9ef110a6ad6fcdc30569d (patch) | |
tree | ee87664a70f156495f9572def6e002772b710a7c | |
parent | 7e95e6a14260e2598ac9d4ea3d088dbde0c08776 (diff) | |
download | mongo-a9e694a18f25775764c9ef110a6ad6fcdc30569d.tar.gz |
SERVER-22053 Insertion of Array with undefined/null components
(cherry picked from commit af198512c7dbb00442fb5115aeac661bf85535c8)
lint fix
(cherry picked from commit 9c3c7d8328d50d45206d310d5c63f0197f49ab39)
-rw-r--r-- | jstests/core/server22053.js | 19 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/objectwrapper.cpp | 40 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/objectwrapper.h | 2 |
3 files changed, 54 insertions, 7 deletions
diff --git a/jstests/core/server22053.js b/jstests/core/server22053.js new file mode 100644 index 00000000000..5549dbc95ee --- /dev/null +++ b/jstests/core/server22053.js @@ -0,0 +1,19 @@ +(function() { + + "use strict"; + var t = db.jstests_server22053; + + /* eslint-disable no-sparse-arrays */ + var s0 = [, , 3, , , 6]; + t.coll.insert({mys: s0}); + + var cur = t.coll.find(); + var doc = cur.next(); + assert.eq(6, doc['mys'].length); + assert.eq(undefined, doc['mys'][0]); + assert.eq(undefined, doc['mys'][1]); + assert.eq(3, doc['mys'][2]); + assert.eq(undefined, doc['mys'][3]); + assert.eq(undefined, doc['mys'][4]); + assert.eq(6, doc['mys'][5]); +}()); diff --git a/src/mongo/scripting/mozjs/objectwrapper.cpp b/src/mongo/scripting/mozjs/objectwrapper.cpp index 969e22b95d8..77ea9a1eca8 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.cpp +++ b/src/mongo/scripting/mozjs/objectwrapper.cpp @@ -31,6 +31,7 @@ #include "mongo/scripting/mozjs/objectwrapper.h" #include <js/Conversions.h> +#include <jsapi.h> #include "mongo/base/error_codes.h" #include "mongo/bson/bsonobjbuilder.h" @@ -537,15 +538,42 @@ ObjectWrapper::WriteFieldRecursionFrame::WriteFieldRecursionFrame(JSContext* cx, JSObject* obj, BSONObjBuilder* parent, StringData sd) - : thisv(cx, obj), ids(cx, JS_Enumerate(cx, thisv)) { + : thisv(cx, obj), ids(cx) { + bool isArray = false; if (parent) { - subbob.emplace(JS_IsArrayObject(cx, thisv) ? parent->subarrayStart(sd) - : parent->subobjStart(sd)); + isArray = JS_IsArrayObject(cx, thisv); + + subbob.emplace(isArray ? parent->subarrayStart(sd) : parent->subobjStart(sd)); } - if (!ids) { - throwCurrentJSException( - cx, ErrorCodes::JSInterpreterFailure, "Failure to enumerate object"); + if (isArray) { + uint32_t length; + if (!JS_GetArrayLength(cx, thisv, &length)) { + throwCurrentJSException( + cx, ErrorCodes::JSInterpreterFailure, "Failure to get array length"); + } + + if (!ids.reserve(length)) { + throwCurrentJSException( + cx, ErrorCodes::JSInterpreterFailure, "Failure to reserve array"); + } + + JS::RootedId rid(cx); + for (uint32_t i = 0; i < length; i++) { + rid.set(INT_TO_JSID(i)); + ids.infallibleAppend(rid); + } + } else { + JS::AutoIdArray rids(cx, JS_Enumerate(cx, thisv)); + + if (!ids.reserve(rids.length())) { + throwCurrentJSException( + cx, ErrorCodes::JSInterpreterFailure, "Failure to reserve array"); + } + + for (uint32_t i = 0; i < rids.length(); i++) { + ids.infallibleAppend(rids[i]); + } } if (getScope(cx)->getProto<BSONInfo>().instanceOf(thisv)) { diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h index 42be21ff36f..983c662efb3 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.h +++ b/src/mongo/scripting/mozjs/objectwrapper.h @@ -198,7 +198,7 @@ private: JS::RootedObject thisv; // ids for the keys of thisv - JS::AutoIdArray ids; + JS::AutoIdVector ids; // Current index of the current key we're working on std::size_t idx = 0; |