summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaley Chen <waleycz@gmail.com>2016-08-02 11:53:25 -0400
committerJason Carey <jcarey@argv.me>2017-05-04 13:33:01 -0400
commita9e694a18f25775764c9ef110a6ad6fcdc30569d (patch)
treeee87664a70f156495f9572def6e002772b710a7c
parent7e95e6a14260e2598ac9d4ea3d088dbde0c08776 (diff)
downloadmongo-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.js19
-rw-r--r--src/mongo/scripting/mozjs/objectwrapper.cpp40
-rw-r--r--src/mongo/scripting/mozjs/objectwrapper.h2
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;