Ignore:
Timestamp:
Dec 14, 2017, 11:11:49 AM (7 years ago)
Author:
[email protected]
Message:

JSObjects should have a mask for loading indexed properties
https://bugs.webkit.org/show_bug.cgi?id=180768

Reviewed by Mark Lam.

JSTests:

  • stress/int16-put-by-val-in-and-out-of-bounds.js:

(test):

Source/JavaScriptCore:

This patch adds a new member to JSObject that holds an indexing
mask. The indexing mask is bitwise anded with the index used to
load a property. If for whatever reason an attacker is able to
clobber the vectorLength of our butterfly they still won't be able
to read substantially past the end of the buttefly. For
performance reasons we don't use the indexing masking for
TypedArrays. Since TypedArrays are already gigacaged the risk of
wild reads is still restricted.

This patch is a <1% regression on Speedometer and ~3% regression
on JetStream in my testing.

  • assembler/MacroAssembler.h:

(JSC::MacroAssembler::urshiftPtr):

  • bytecode/AccessCase.cpp:

(JSC::AccessCase::generateImpl):

  • dfg/DFGAbstractHeap.h:
  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::emitAllocateRawObject):
(JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
(JSC::DFG::SpeculativeJIT::compileNewFunctionCommon):
(JSC::DFG::SpeculativeJIT::compileCreateActivation):
(JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
(JSC::DFG::SpeculativeJIT::compileArraySlice):
(JSC::DFG::SpeculativeJIT::compileNukeStructureAndSetButterfly):
(JSC::DFG::SpeculativeJIT::compileNewStringObject):
(JSC::DFG::SpeculativeJIT::compileNewTypedArray):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::emitAllocateJSObject):
(JSC::DFG::SpeculativeJIT::emitAllocateJSObjectWithKnownSize):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):

  • ftl/FTLAbstractHeap.cpp:

(JSC::FTL::IndexedAbstractHeap::baseIndex):

  • ftl/FTLAbstractHeap.h:
  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileAtomicsReadModifyWrite):
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateActivation):
(JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
(JSC::FTL::DFG::LowerDFGToB3::compileNewStringObject):
(JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeCreateActivation):
(JSC::FTL::DFG::LowerDFGToB3::maskedIndex):
(JSC::FTL::DFG::LowerDFGToB3::computeButterflyIndexingMask):
(JSC::FTL::DFG::LowerDFGToB3::allocateObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedObject):
(JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
(JSC::FTL::DFG::LowerDFGToB3::pointerIntoTypedArray):

  • ftl/FTLOutput.h:

(JSC::FTL::Output::baseIndex):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitComputeButterflyIndexingMask):
(JSC::AssemblyHelpers::nukeStructureAndStoreButterfly):
(JSC::AssemblyHelpers::emitAllocateJSObject):
(JSC::AssemblyHelpers::emitAllocateJSObjectWithKnownSize):
(JSC::AssemblyHelpers::emitAllocateVariableSizedJSObject):
(JSC::AssemblyHelpers::emitAllocateDestructibleObject):
(JSC::AssemblyHelpers::storeButterfly): Deleted.

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_new_object):
(JSC::JIT::emit_op_create_this):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_new_object):
(JSC::JIT::emit_op_create_this):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitDoubleLoad):
(JSC::JIT::emitContiguousLoad):
(JSC::JIT::emitArrayStorageLoad):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/ArrayStorage.h:

(JSC::ArrayStorage::availableVectorLength):

  • runtime/Butterfly.h:

(JSC::ContiguousData::ContiguousData):
(JSC::ContiguousData::at const):
(JSC::ContiguousData::at):
(JSC::Butterfly::publicLength const):
(JSC::Butterfly::vectorLength const):
(JSC::Butterfly::computeIndexingMaskForVectorLength):
(JSC::Butterfly::computeIndexingMask):
(JSC::Butterfly::contiguousInt32):
(JSC::ContiguousData::operator[] const): Deleted.
(JSC::ContiguousData::operator[]): Deleted.
(JSC::Butterfly::publicLength): Deleted.
(JSC::Butterfly::vectorLength): Deleted.

  • runtime/ButterflyInlines.h:

(JSC::ContiguousData<T>::at const):
(JSC::ContiguousData<T>::at):

  • runtime/ClonedArguments.cpp:

(JSC::ClonedArguments::createEmpty):

  • runtime/JSArray.cpp:

(JSC::JSArray::tryCreateUninitializedRestricted):
(JSC::JSArray::appendMemcpy):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::fastSlice):
(JSC::JSArray::shiftCountWithArrayStorage):
(JSC::JSArray::shiftCountWithAnyIndexingType):
(JSC::JSArray::unshiftCountWithAnyIndexingType):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):

  • runtime/JSArrayBufferView.cpp:

(JSC::JSArrayBufferView::JSArrayBufferView):

  • runtime/JSArrayInlines.h:

(JSC::JSArray::pushInline):

  • runtime/JSFixedArray.h:

(JSC::JSFixedArray::createFromArray):

  • runtime/JSGenericTypedArrayViewInlines.h:

(JSC::JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory):

  • runtime/JSObject.cpp:

(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::putByIndex):
(JSC::JSObject::createInitialInt32):
(JSC::JSObject::createInitialDouble):
(JSC::JSObject::createInitialContiguous):
(JSC::JSObject::convertUndecidedToInt32):
(JSC::JSObject::convertUndecidedToDouble):
(JSC::JSObject::convertUndecidedToContiguous):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToArrayStorage):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::convertDoubleToArrayStorage):
(JSC::JSObject::convertContiguousToArrayStorage):
(JSC::JSObject::createInitialForValueAndSet):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::countElements):
(JSC::JSObject::ensureLengthSlow):
(JSC::JSObject::reallocateAndShrinkButterfly):
(JSC::JSObject::getEnumerableLength):

  • runtime/JSObject.h:

(JSC::JSObject::canGetIndexQuickly):
(JSC::JSObject::getIndexQuickly):
(JSC::JSObject::tryGetIndexQuickly const):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::initializeIndexWithoutBarrier):
(JSC::JSObject::butterflyIndexingMaskOffset):
(JSC::JSObject::butterflyIndexingMask const):
(JSC::JSObject::setButterflyWithIndexingMask):
(JSC::JSObject::setButterfly):
(JSC::JSObject::nukeStructureAndSetButterfly):
(JSC::JSObject::JSObject):

  • runtime/RegExpMatchesArray.h:

(JSC::tryCreateUninitializedRegExpMatchesArray):

  • runtime/Structure.cpp:

(JSC::Structure::flattenDictionaryStructure):

Source/WebCore:

  • bindings/js/JSDOMConvertSequences.h:

(WebCore::Detail::NumericSequenceConverter::convertArray):
(WebCore::Detail::SequenceConverter::convertArray):

Source/WTF:

Add a clz that wraps the builtin clz intrinisics provided by
various compilers. The clz function by default assumes that
the input may be zero. On X86 this makes a difference because not
all CPUs have LZCNT and BSR has undefined behavior on zero. On ARM,
the zero check gets optimized away, regardless.

  • wtf/StdLibExtras.h:

(std::clz):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r225697 r225913  
    15011501    bieq t2, Int32Shape, .opGetByValIsContiguous
    15021502    bineq t2, ContiguousShape, .opGetByValNotContiguous
     1503
    15031504.opGetByValIsContiguous:
    1504 
    15051505    biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
     1506    andi JSObject::m_butterflyIndexingMask[t0], t1
    15061507    loadisFromInstruction(1, t0)
    15071508    loadq [t3, t1, 8], t2
     
    15121513    bineq t2, DoubleShape, .opGetByValNotDouble
    15131514    biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
    1514     loadis 8[PB, PC, 8], t0
     1515    andi JSObject::m_butterflyIndexingMask[t0], t1
     1516    loadisFromInstruction(1 ,t0)
    15151517    loadd [t3, t1, 8], ft0
    15161518    bdnequn ft0, ft0, .opGetByValOutOfBounds
     
    15231525    bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValNotIndexedStorage
    15241526    biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
     1527    andi JSObject::m_butterflyIndexingMask[t0], t1
    15251528    loadisFromInstruction(1, t0)
    15261529    loadq ArrayStorage::m_vector[t3, t1, 8], t2
Note: See TracChangeset for help on using the changeset viewer.