JSON.parse has bad is array assert
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Oct 2019 23:23:37 +0000 (23:23 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Oct 2019 23:23:37 +0000 (23:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203207
<rdar://problem/56366913>

Reviewed by Yusuke Suzuki.

JSTests:

* stress/json-parse-array-prototype-is-array-assert.js: Added.
(assert):

Source/JavaScriptCore:

In r250860, we updated JSON.parse to be more spec compliant with how it
handles arrays. However, we also updated an assertion in an improper way,
where our assert was not accounting for the check we performed to take
that control flow path.

* runtime/JSONObject.cpp:
(JSC::Walker::walk):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@251394 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/json-parse-array-prototype-is-array-assert.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSONObject.cpp

index 581adf9..8aaafda 100644 (file)
@@ -1,3 +1,14 @@
+2019-10-21  Saam Barati  <sbarati@apple.com>
+
+        JSON.parse has bad is array assert
+        https://bugs.webkit.org/show_bug.cgi?id=203207
+        <rdar://problem/56366913>
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/json-parse-array-prototype-is-array-assert.js: Added.
+        (assert):
+
 2019-10-21  Robin Morisset  <rmorisset@apple.com>
 
         Throw the right exception upon memory exhaustion in Array::slice
 2019-10-21  Robin Morisset  <rmorisset@apple.com>
 
         Throw the right exception upon memory exhaustion in Array::slice
diff --git a/JSTests/stress/json-parse-array-prototype-is-array-assert.js b/JSTests/stress/json-parse-array-prototype-is-array-assert.js
new file mode 100644 (file)
index 0000000..cb8d5cc
--- /dev/null
@@ -0,0 +1,28 @@
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+assert(JSON.stringify(JSON.parse('[1337,42]', function (x, y) {
+    if (this instanceof Array) {
+        Object.defineProperty(this, '1', {value: Array.prototype});
+        return y;
+    }
+    return this;
+})) === '{"":[1337,[]]}');
+
+assert(JSON.stringify(JSON.parse('[0, 1]', function(x, y) {
+    this[1] = Array.prototype;
+    return y;
+})) === '[0,[]]');
+
+assert(JSON.stringify(JSON.parse('{"x":22, "y":44}', function(a, b) {
+    this.y = Array.prototype;
+    return b;
+})) === '{"x":22,"y":[]}');
+
+Array.prototype[0] = 42;
+assert(JSON.stringify(JSON.parse('{"x":22, "y":44}', function(a, b) {
+    this.y = Array.prototype;
+    return b;
+})) === '{"x":22,"y":[42]}');
index 593058d..2ce0dfd 100644 (file)
@@ -1,3 +1,19 @@
+2019-10-21  Saam Barati  <sbarati@apple.com>
+
+        JSON.parse has bad is array assert
+        https://bugs.webkit.org/show_bug.cgi?id=203207
+        <rdar://problem/56366913>
+
+        Reviewed by Yusuke Suzuki.
+
+        In r250860, we updated JSON.parse to be more spec compliant with how it
+        handles arrays. However, we also updated an assertion in an improper way,
+        where our assert was not accounting for the check we performed to take
+        that control flow path.
+
+        * runtime/JSONObject.cpp:
+        (JSC::Walker::walk):
+
 2019-10-21  Robin Morisset  <rmorisset@apple.com>
 
         Throw the right exception upon memory exhaustion in Array::slice
 2019-10-21  Robin Morisset  <rmorisset@apple.com>
 
         Throw the right exception upon memory exhaustion in Array::slice
index 07c511c..dcb176e 100644 (file)
@@ -664,7 +664,9 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(isJSArray(inValue) || inValue.inherits<ProxyObject>(vm));
+                ASSERT(isArray(m_exec, inValue));
+                EXCEPTION_ASSERT(!scope.exception());
+
                 if (markedStack.size() > maximumFilterRecursion)
                     return throwStackOverflowError(m_exec, scope);
 
                 if (markedStack.size() > maximumFilterRecursion)
                     return throwStackOverflowError(m_exec, scope);