The new array with spread operation needs to check for length overflows.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Mar 2017 21:53:33 +0000 (21:53 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Mar 2017 21:53:33 +0000 (21:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169780
<rdar://problem/31072182>

Reviewed by Filip Pizlo.

* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewArrayWithSpread):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* llint/LLIntSlowPaths.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/JSGlobalObject.cpp:

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLOperations.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp

index 1cd1790..82841f8 100644 (file)
@@ -1,3 +1,23 @@
+2017-03-16  Mark Lam  <mark.lam@apple.com>
+
+        The new array with spread operation needs to check for length overflows.
+        https://bugs.webkit.org/show_bug.cgi?id=169780
+        <rdar://problem/31072182>
+
+        Reviewed by Filip Pizlo.
+
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewArrayWithSpread):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationMaterializeObjectInOSR):
+        * llint/LLIntSlowPaths.cpp:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/JSGlobalObject.cpp:
+
 2017-03-16  Filip Pizlo  <fpizlo@apple.com>
 
         FTL should support global and eval code
index 6e3a7e0..35ae636 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1998,16 +1998,21 @@ JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buf
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
-    unsigned length = 0;
+    Checked<unsigned, RecordOverflow> checkedLength = 0;
     for (unsigned i = 0; i < numItems; i++) {
         JSValue value = JSValue::decode(values[i]);
         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
-            length += array->size();
+            checkedLength += array->size();
         else
-            ++length;
+            ++checkedLength;
     }
 
+    if (UNLIKELY(checkedLength.hasOverflowed())) {
+        throwOutOfMemoryError(exec, scope);
+        return nullptr;
+    }
 
+    unsigned length = checkedLength.unsafeGet();
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
 
index 07c82c4..f3273fc 100644 (file)
@@ -7133,7 +7133,7 @@ void SpeculativeJIT::compileNewArrayWithSpread(Node* node)
                     Edge use = m_jit.graph().varArgChild(node, i);
                     SpeculateCellOperand fixedArray(this, use);
                     GPRReg fixedArrayGPR = fixedArray.gpr();
-                    m_jit.add32(MacroAssembler::Address(fixedArrayGPR, JSFixedArray::offsetOfSize()), lengthGPR);
+                    speculationCheck(Overflow, JSValueRegs(), nullptr, m_jit.branchAdd32(MacroAssembler::Overflow, MacroAssembler::Address(fixedArrayGPR, JSFixedArray::offsetOfSize()), lengthGPR));
                 }
             }
 
index 9719136..1235307 100644 (file)
@@ -4456,6 +4456,7 @@ private:
             for (unsigned i = 0; i < m_node->numChildren(); ++i) {
                 if (bitVector->get(i)) {
                     Edge use = m_graph.varArgChild(m_node, i);
+                    CheckValue* lengthCheck = nullptr;
                     if (use->op() == PhantomSpread) {
                         RELEASE_ASSERT(use->child1()->op() == PhantomCreateRest);
                         InlineCallFrame* inlineCallFrame = use->child1()->origin.semantic.inlineCallFrame;
@@ -4463,11 +4464,13 @@ private:
                         LValue spreadLength = cachedSpreadLengths.ensure(inlineCallFrame, [&] () {
                             return getSpreadLengthFromInlineCallFrame(inlineCallFrame, numberOfArgumentsToSkip);
                         }).iterator->value;
-                        length = m_out.add(length, spreadLength);
+                        lengthCheck = m_out.speculateAdd(length, spreadLength);
                     } else {
                         LValue fixedArray = lowCell(use);
-                        length = m_out.add(length, m_out.load32(fixedArray, m_heaps.JSFixedArray_size));
+                        lengthCheck = m_out.speculateAdd(length, m_out.load32(fixedArray, m_heaps.JSFixedArray_size));
                     }
+                    blessSpeculation(lengthCheck, Overflow, noValue(), nullptr, m_origin);
+                    length = lengthCheck;
                 }
             }
 
index faf614a..50f4717 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -438,7 +438,7 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
         JSGlobalObject* globalObject = codeBlock->globalObject();
         Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
 
-        unsigned arraySize = 0;
+        Checked<unsigned, RecordOverflow> checkedArraySize = 0;
         unsigned numProperties = 0;
         for (unsigned i = materialization->properties().size(); i--;) {
             const ExitPropertyValue& property = materialization->properties()[i];
@@ -446,12 +446,13 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
                 ++numProperties;
                 JSValue value = JSValue::decode(values[i]);
                 if (JSFixedArray* fixedArray = jsDynamicCast<JSFixedArray*>(vm, value))
-                    arraySize += fixedArray->size();
+                    checkedArraySize += fixedArray->size();
                 else
-                    arraySize += 1;
+                    checkedArraySize += 1;
             }
         }
 
+        unsigned arraySize = checkedArraySize.unsafeGet(); // Crashes if overflowed.
         JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, structure, arraySize);
         RELEASE_ASSERT(result);
 
index b5095ff..28ee980 100644 (file)
@@ -47,7 +47,6 @@
 #include "JSAsyncFunction.h"
 #include "JSCInlines.h"
 #include "JSCJSValue.h"
-#include "JSFixedArray.h"
 #include "JSGeneratorFunction.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSLexicalEnvironment.h"
index 53ccad5..bbcb03f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -993,16 +993,19 @@ SLOW_PATH_DECL(slow_path_new_array_with_spread)
 
     JSValue* values = bitwise_cast<JSValue*>(&OP(2));
 
-    unsigned arraySize = 0;
+    Checked<unsigned, RecordOverflow> checkedArraySize = 0;
     for (int i = 0; i < numItems; i++) {
         if (bitVector.get(i)) {
             JSValue value = values[-i];
             JSFixedArray* array = jsCast<JSFixedArray*>(value);
-            arraySize += array->size();
+            checkedArraySize += array->size();
         } else
-            arraySize += 1;
+            checkedArraySize += 1;
     }
+    if (UNLIKELY(checkedArraySize.hasOverflowed()))
+        THROW(createOutOfMemoryError(exec));
 
+    unsigned arraySize = checkedArraySize.unsafeGet();
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
 
index 8e6ef58..bcbcb6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009, 2014-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *
  * Redistribution and use in source and binary forms, with or without
@@ -80,7 +80,6 @@
 #include "JSDataViewPrototype.h"
 #include "JSDollarVM.h"
 #include "JSDollarVMPrototype.h"
-#include "JSFixedArray.h"
 #include "JSFunction.h"
 #include "JSGeneratorFunction.h"
 #include "JSGenericTypedArrayViewConstructorInlines.h"