Contiguous storage butterfly length should not exceed MAX_STORAGE_VECTOR_LENGTH.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Jun 2017 00:28:47 +0000 (00:28 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Jun 2017 00:28:47 +0000 (00:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=173035
<rdar://problem/32554593>

Reviewed by Geoffrey Garen and Filip Pizlo.

JSTests:

* stress/regress-173035.js: Added.

Source/JavaScriptCore:

Also added and fixed up some assertions.

* runtime/ArrayConventions.h:
* runtime/JSArray.cpp:
(JSC::JSArray::setLength):
* runtime/JSObject.cpp:
(JSC::JSObject::createInitialIndexedStorage):
(JSC::JSObject::ensureLengthSlow):
(JSC::JSObject::reallocateAndShrinkButterfly):
* runtime/JSObject.h:
(JSC::JSObject::ensureLength):
* runtime/RegExpObject.cpp:
(JSC::collectMatches):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncSplitFast):

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

JSTests/ChangeLog
JSTests/stress/regress-173035.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/ArrayConventions.h
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/RegExpPrototype.cpp

index 11a472a..bae9630 100644 (file)
@@ -1,3 +1,13 @@
+2017-06-06  Mark Lam  <mark.lam@apple.com>
+
+        Contiguous storage butterfly length should not exceed MAX_STORAGE_VECTOR_LENGTH.
+        https://bugs.webkit.org/show_bug.cgi?id=173035
+        <rdar://problem/32554593>
+
+        Reviewed by Geoffrey Garen and Filip Pizlo.
+
+        * stress/regress-173035.js: Added.
+
 2017-06-06  Saam Barati  <sbarati@apple.com>
 
         Make sure we restore SP when doing calls that could be to JS
diff --git a/JSTests/stress/regress-173035.js b/JSTests/stress/regress-173035.js
new file mode 100644 (file)
index 0000000..d251246
--- /dev/null
@@ -0,0 +1,4 @@
+var a = [];
+for (var i=0; i<0x04001000; i++) a.push(i+0.1);
+a.length = 0x20000000;
+a.slice(0x1fffffff,0x20000000);
index 75e558e..b2ae091 100644 (file)
@@ -1,3 +1,27 @@
+2017-06-06  Mark Lam  <mark.lam@apple.com>
+
+        Contiguous storage butterfly length should not exceed MAX_STORAGE_VECTOR_LENGTH.
+        https://bugs.webkit.org/show_bug.cgi?id=173035
+        <rdar://problem/32554593>
+
+        Reviewed by Geoffrey Garen and Filip Pizlo.
+
+        Also added and fixed up some assertions.
+
+        * runtime/ArrayConventions.h:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::setLength):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::createInitialIndexedStorage):
+        (JSC::JSObject::ensureLengthSlow):
+        (JSC::JSObject::reallocateAndShrinkButterfly):
+        * runtime/JSObject.h:
+        (JSC::JSObject::ensureLength):
+        * runtime/RegExpObject.cpp:
+        (JSC::collectMatches):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncSplitFast):
+
 2017-06-06  Saam Barati  <sbarati@apple.com>
 
         Make sure we restore SP when doing calls that could be to JS
index 6aacb97..0e32eb9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008, 2009, 2012, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -69,6 +69,9 @@ namespace JSC {
 // 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer.
 #define MAX_ARRAY_INDEX 0xFFFFFFFEU
 
+static_assert(MIN_SPARSE_ARRAY_INDEX <= MAX_STORAGE_VECTOR_INDEX, "MIN_SPARSE_ARRAY_INDEX must be less than or equal to MAX_STORAGE_VECTOR_INDEX");
+static_assert(MAX_STORAGE_VECTOR_INDEX <= MAX_ARRAY_INDEX, "MAX_STORAGE_VECTOR_INDEX must be less than or equal to MAX_ARRAY_INDEX");
+
 // The value BASE_XXX_VECTOR_LEN is the maximum number of vector elements we'll allocate
 // for an array that was created with a sepcified length (e.g. a = new Array(123))
 #define BASE_CONTIGUOUS_VECTOR_LEN 3U
index a9f4a82..3cb4dfe 100644 (file)
@@ -569,7 +569,7 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
     case ArrayWithContiguous: {
         if (newLength == butterfly->publicLength())
             return true;
-        if (newLength >= MAX_ARRAY_INDEX // This case ensures that we can do fast push.
+        if (newLength > MAX_STORAGE_VECTOR_LENGTH // This check ensures that we can do fast push.
             || (newLength >= MIN_SPARSE_ARRAY_INDEX
                 && !isDenseEnoughForVector(newLength, countElements()))) {
             scope.release();
index 77f4736..b71bd4e 100644 (file)
@@ -1001,7 +1001,7 @@ void JSObject::notifyPresenceOfIndexedAccessors(VM& vm)
 
 Butterfly* JSObject::createInitialIndexedStorage(VM& vm, unsigned length)
 {
-    ASSERT(length < MAX_ARRAY_INDEX);
+    ASSERT(length <= MAX_STORAGE_VECTOR_LENGTH);
     IndexingType oldType = indexingType();
     ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
     ASSERT(!structure()->needsSlowPutIndexing());
@@ -3129,7 +3129,7 @@ bool JSObject::ensureLengthSlow(VM& vm, unsigned length)
 {
     Butterfly* butterfly = m_butterfly.get();
     
-    ASSERT(length < MAX_ARRAY_INDEX);
+    ASSERT(length <= MAX_STORAGE_VECTOR_LENGTH);
     ASSERT(hasContiguous(indexingType()) || hasInt32(indexingType()) || hasDouble(indexingType()) || hasUndecided(indexingType()));
     ASSERT(length > butterfly->vectorLength());
     
@@ -3181,8 +3181,7 @@ bool JSObject::ensureLengthSlow(VM& vm, unsigned length)
 
 void JSObject::reallocateAndShrinkButterfly(VM& vm, unsigned length)
 {
-    ASSERT(length < MAX_ARRAY_INDEX);
-    ASSERT(length < MAX_STORAGE_VECTOR_LENGTH);
+    ASSERT(length <= MAX_STORAGE_VECTOR_LENGTH);
     ASSERT(hasContiguous(indexingType()) || hasInt32(indexingType()) || hasDouble(indexingType()) || hasUndecided(indexingType()));
     ASSERT(m_butterfly.get()->vectorLength() > length);
     ASSERT(!m_butterfly.get()->indexingHeader()->preCapacity(structure()));
index d35419a..f4615bf 100644 (file)
@@ -967,7 +967,7 @@ protected:
     // the array is contiguous.
     bool WARN_UNUSED_RETURN ensureLength(VM& vm, unsigned length)
     {
-        ASSERT(length < MAX_ARRAY_INDEX);
+        ASSERT(length <= MAX_STORAGE_VECTOR_LENGTH);
         ASSERT(hasContiguous(indexingType()) || hasInt32(indexingType()) || hasDouble(indexingType()) || hasUndecided(indexingType()));
 
         if (m_butterfly.get()->vectorLength() < length) {
index 4a4deac..8de93b0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007-2008, 2012, 2016 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -204,7 +204,7 @@ JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String&
             unsigned matchCount = 0;
             MatchResult savedResult = result;
             do {
-                if (array->length() + matchCount >= MAX_STORAGE_VECTOR_LENGTH) {
+                if (array->length() + matchCount > MAX_STORAGE_VECTOR_LENGTH) {
                     throwOutOfMemoryError(exec, scope);
                     return jsUndefined();
                 }
index 35c7238..5a8f0a1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007-2008, 2016 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -679,7 +679,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncSplitFast(ExecState* exec)
     genericSplit(
         vm, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
         [&] () -> SplitControl {
-            if (resultLength + dryRunCount >= MAX_STORAGE_VECTOR_LENGTH)
+            if (resultLength + dryRunCount > MAX_STORAGE_VECTOR_LENGTH)
                 return AbortSplit;
             return ContinueSplit;
         },
@@ -690,7 +690,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncSplitFast(ExecState* exec)
             return ContinueSplit;
         });
     
-    if (resultLength + dryRunCount >= MAX_STORAGE_VECTOR_LENGTH) {
+    if (resultLength + dryRunCount > MAX_STORAGE_VECTOR_LENGTH) {
         throwOutOfMemoryError(exec, scope);
         return encodedJSValue();
     }