Permalink
Browse files

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:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@214071 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information...
mark.lam@apple.com
mark.lam@apple.com committed Mar 16, 2017
1 parent 09aebb5 commit 61dbb71d92f6a9e5a72c5f784eb5ed11495b3ff7
@@ -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
@@ -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);

@@ -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));
}
}

@@ -4456,18 +4456,21 @@ class LowerDFGToB3 {
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;
unsigned numberOfArgumentsToSkip = use->child1()->numberOfArgumentsToSkip();
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;
}
}

@@ -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,20 +438,21 @@ 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];
if (property.location().kind() == NewArrayWithSpreadArgumentPLoc) {
++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);

@@ -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"
@@ -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);

@@ -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"

0 comments on commit 61dbb71

Please sign in to comment.