Title: [227886] branches/safari-605-branch/Source
Revision
227886
Author
[email protected]
Date
2018-01-31 01:09:31 -0800 (Wed, 31 Jan 2018)

Log Message

Cherry-pick r227874. rdar://problem/37059537

Modified Paths

Diff

Modified: branches/safari-605-branch/Source/_javascript_Core/ChangeLog (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/ChangeLog	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/ChangeLog	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,3 +1,134 @@
+2018-01-31  Jason Marcell  <[email protected]>
+
+        Cherry-pick r227874. rdar://problem/37059537
+
+    2018-01-30  Mark Lam  <[email protected]>
+
+            Apply poisoning to TypedArray vector pointers.
+            https://bugs.webkit.org/show_bug.cgi?id=182155
+            <rdar://problem/36286266>
+
+            Reviewed by JF Bastien.
+
+            The TypeArray's vector pointer is now poisoned.  The poison value is chosen based
+            on a TypeArray's jsType.  The JSType must be between FirstTypedArrayType and
+            LastTypedArrayType.  At runtime, we enforce that the index is well-behaved by
+            masking it against TypedArrayPoisonIndexMask.  TypedArrayPoisonIndexMask (16) is
+            the number of TypedArray types (10) rounded up to the next power of 2.
+            Accordingly, we reserve an array of TypedArrayPoisonIndexMask poisons so that we
+            can use index masking on the index, and be guaranteed that the masked index will
+            be within bounds of the poisons array.
+
+            1. Fixed both DFG and FTL versions of compileGetTypedArrayByteOffset() to not
+               do any unnecessary work if the TypedArray vector is null.
+
+               FTL's cagedMayBeNull() is no longer needed because it is only used by
+               compileGetTypedArrayByteOffset(), and we need to enhance it to handle unpoisoning
+               in a TypedArray specific way.  So, might as well do the work inline in
+               compileGetTypedArrayByteOffset() instead.
+
+            2. Removed an unnecessary null-check in DFGSpeculativeJIT's compileNewTypedArrayWithSize()
+               because there's already a null check above it that ensures that sizeGPR is
+               never null.
+
+            3. In LLInt's _llint_op_get_by_val, move the TypedArray length check before the
+               loading of the vector for unpoisoning and uncaging.  We don't need the vector
+               if the length is 0.
+
+            Implementation notes on the need to null check the TypeArray vector:
+
+            1. DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds() does not need a
+               m_poisonedVector null check because the function is a null check.
+
+            2. DFG::SpeculativeJIT::compileGetIndexedPropertyStorage() does not need a
+               m_poisonedVector null check because it is followed by a call to
+               cageTypedArrayStorage() which assumes that storageReg cannot be null.
+
+            3. DFG::SpeculativeJIT::compileGetTypedArrayByteOffset() already has a
+               m_poisonedVector null check.
+
+            4. DFG::SpeculativeJIT::compileNewTypedArrayWithSize() does not need a vector null
+               check because the poisoning code is preceded by a sizeGPR null check, which
+               ensures that the storageGPR (vector to be poisoned) is not null.
+
+            5. FTL's compileGetIndexedPropertyStorage() does not need a m_poisonedVector null
+               check because it is followed by a call to caged() which assumes that the
+               vector cannot be null.
+
+            6. FTL's compileGetTypedArrayByteOffset() already has a m_poisonedVector null check.
+
+            7. FTL's compileNewTypedArray() does not need a vector null check because the
+               poisoning code is preceded by a size null check, which ensures that the
+               storage (vector to be poisoned) is not null.
+
+            8. FTL's speculateTypedArrayIsNotNeutered() does not need a
+               m_poisonedVector null check because the function is a null check.
+
+            9. IntrinsicGetterAccessCase::emitIntrinsicGetter()'s TypedArrayByteOffsetIntrinsic
+               case needs a null check so that it does not try to unpoison a null vector.
+
+            10. JIT::emitIntTypedArrayGetByVal() does not need a vector null check because
+                we already do a length check even before loading the vector.
+
+            11. JIT::emitFloatTypedArrayGetByVal() does not need a vector null check because
+                we already do a length check even before loading the vector.
+
+            12. JIT::emitIntTypedArrayPutByVal() does not need a vector null check because
+                we already do a length check even before loading the vector.
+
+            13. JIT::emitFloatTypedArrayPutByVal() does not need a vector null check because
+                we already do a length check even before loading the vector.
+
+            14. LLInt's loadTypedArrayCaged() does not need a vector null check because its
+                client will do a TypedArray length check before calling it.
+
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::checkArray):
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::hasArrayMode):
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds):
+            (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
+            (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
+            (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize):
+            * ftl/FTLAbstractHeapRepository.h:
+            * ftl/FTLLowerDFGToB3.cpp:
+            (JSC::FTL::DFG::LowerDFGToB3::compileGetIndexedPropertyStorage):
+            (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffset):
+            (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
+            (JSC::FTL::DFG::LowerDFGToB3::speculateTypedArrayIsNotNeutered):
+            (JSC::FTL::DFG::LowerDFGToB3::cagedMayBeNull): Deleted.
+            * jit/IntrinsicEmitter.cpp:
+            (JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter):
+            * jit/JITPropertyAccess.cpp:
+            (JSC::JIT::emitIntTypedArrayGetByVal):
+            (JSC::JIT::emitFloatTypedArrayGetByVal):
+            (JSC::JIT::emitIntTypedArrayPutByVal):
+            (JSC::JIT::emitFloatTypedArrayPutByVal):
+            * llint/LowLevelInterpreter.asm:
+            * llint/LowLevelInterpreter64.asm:
+            * offlineasm/arm64.rb:
+            * offlineasm/x86.rb:
+            * runtime/CagedBarrierPtr.h:
+            * runtime/JSArrayBufferView.cpp:
+            (JSC::JSArrayBufferView::JSArrayBufferView):
+            (JSC::JSArrayBufferView::finalize):
+            (JSC::JSArrayBufferView::neuter):
+            * runtime/JSArrayBufferView.h:
+            (JSC::JSArrayBufferView::vector const):
+            (JSC::JSArrayBufferView::offsetOfPoisonedVector):
+            (JSC::JSArrayBufferView::poisonFor):
+            (JSC::JSArrayBufferView::Poison::key):
+            (JSC::JSArrayBufferView::offsetOfVector): Deleted.
+            * runtime/JSCPoison.cpp:
+            (JSC::initializePoison):
+            * runtime/JSCPoison.h:
+            * runtime/JSGenericTypedArrayViewInlines.h:
+            (JSC::JSGenericTypedArrayView<Adaptor>::estimatedSize):
+            (JSC::JSGenericTypedArrayView<Adaptor>::visitChildren):
+            (JSC::JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory):
+            * runtime/JSObject.h:
+
 2018-01-30  Jason Marcell  <[email protected]>
 
         Cherry-pick r227649. rdar://problem/37019344

Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -2847,6 +2847,7 @@
                 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
         }
         
+        ASSERT(arrayMode.type() == Array::String || arrayMode.typedArrayType() != NotTypedArray);
         return m_insertionSet.insertNode(
             m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
             OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));

Modified: branches/safari-605-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -2847,7 +2847,7 @@
 
             JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
                 MacroAssembler::Zero,
-                MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
+                MacroAssembler::Address(base, JSArrayBufferView::offsetOfPoisonedVector()));
             speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
             notWasteful.link(&m_jit);
         }
@@ -6357,9 +6357,13 @@
         break;
         
     default:
-        ASSERT(isTypedView(node->arrayMode().typedArrayType()));
+        auto typedArrayType = node->arrayMode().typedArrayType();
+        ASSERT_UNUSED(typedArrayType, isTypedView(typedArrayType));
 
-        m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfVector()), storageReg);
+        m_jit.loadPtr(JITCompiler::Address(baseReg, JSArrayBufferView::offsetOfPoisonedVector()), storageReg);
+#if ENABLE(POISON)
+        m_jit.xorPtr(JITCompiler::TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), storageReg);
+#endif
         cageTypedArrayStorage(storageReg);
         break;
     }
@@ -6376,22 +6380,45 @@
     GPRReg baseGPR = base.gpr();
     GPRReg vectorGPR = vector.gpr();
     GPRReg dataGPR = data.gpr();
-    
+    ASSERT(baseGPR != vectorGPR);
+    ASSERT(baseGPR != dataGPR);
+    ASSERT(vectorGPR != dataGPR);
+
+#if ENABLE(POISON)
+    GPRTemporary poison(this);
+    GPRTemporary index(this);
+    GPRReg poisonGPR = poison.gpr();
+    GPRReg indexGPR = index.gpr();
+    GPRReg arrayBufferGPR = poisonGPR;
+#else
+    GPRReg arrayBufferGPR = dataGPR;
+#endif
+
     JITCompiler::Jump emptyByteOffset = m_jit.branch32(
         MacroAssembler::NotEqual,
         MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
         TrustedImm32(WastefulTypedArray));
 
+    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfPoisonedVector()), vectorGPR);
+    JITCompiler::Jump nullVector = m_jit.branchTestPtr(JITCompiler::Zero, vectorGPR);
+
     m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
     m_jit.cage(Gigacage::JSValue, dataGPR);
-    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
-    JITCompiler::Jump nullVector = m_jit.branchTestPtr(JITCompiler::Zero, vectorGPR);
+
+#if ENABLE(POISON)
+    m_jit.load8(JITCompiler::Address(baseGPR, JSCell::typeInfoTypeOffset()), indexGPR);
+    m_jit.move(JITCompiler::TrustedImmPtr(&g_typedArrayPoisons), poisonGPR);
+    m_jit.sub32(JITCompiler::TrustedImm32(FirstTypedArrayType), indexGPR);
+    m_jit.and32(JITCompiler::TrustedImm32(TypedArrayPoisonIndexMask), indexGPR);
+    m_jit.loadPtr(JITCompiler::BaseIndex(poisonGPR, indexGPR, JITCompiler::timesPtr()), poisonGPR);
+    m_jit.xorPtr(poisonGPR, vectorGPR);
+#endif
     cageTypedArrayStorage(vectorGPR);
 
-    m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), dataGPR);
+    m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), arrayBufferGPR);
     // FIXME: This needs caging.
     // https://bugs.webkit.org/show_bug.cgi?id=175515
-    m_jit.loadPtr(MacroAssembler::Address(dataGPR, ArrayBuffer::offsetOfData()), dataGPR);
+    m_jit.loadPtr(MacroAssembler::Address(arrayBufferGPR, ArrayBuffer::offsetOfData()), dataGPR);
     m_jit.subPtr(dataGPR, vectorGPR);
     
     JITCompiler::Jump done = m_jit.jump();
@@ -9029,8 +9056,7 @@
     m_jit.emitAllocateVariableSized(
         storageGPR, m_jit.vm()->primitiveGigacageAuxiliarySpace, scratchGPR, scratchGPR,
         scratchGPR2, slowCases);
-    
-    MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, sizeGPR);
+
     m_jit.move(sizeGPR, scratchGPR);
     if (elementSize(typedArrayType) != 4) {
         if (elementSize(typedArrayType) > 4)
@@ -9048,7 +9074,6 @@
         TrustedImm32(0),
         MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesFour));
     m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
-    done.link(&m_jit);
 
     auto butterfly = TrustedImmPtr(nullptr);
     m_jit.emitComputeButterflyIndexingMask(sizeGPR, scratchGPR, indexingMaskGPR);
@@ -9056,9 +9081,17 @@
         resultGPR, TrustedImmPtr(structure), butterfly, indexingMaskGPR, scratchGPR, scratchGPR2,
         slowCases);
 
+#if ENABLE(POISON)
+    m_jit.move(storageGPR, scratchGPR);
+    m_jit.xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), scratchGPR);
     m_jit.storePtr(
+        scratchGPR,
+        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfPoisonedVector()));
+#else
+    m_jit.storePtr(
         storageGPR,
-        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector()));
+        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfPoisonedVector()));
+#endif
     m_jit.store32(
         sizeGPR,
         MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));

Modified: branches/safari-605-branch/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -59,7 +59,7 @@
     macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
     macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
     macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
-    macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
+    macro(JSArrayBufferView_poisonedVector, JSArrayBufferView::offsetOfPoisonedVector()) \
     macro(JSCell_cellState, JSCell::cellStateOffset()) \
     macro(JSCell_header, 0) \
     macro(JSCell_indexingTypeAndMisc, JSCell::indexingTypeAndMiscOffset()) \
@@ -149,7 +149,8 @@
     macro(variables, 0, sizeof(Register)) \
     macro(HasOwnPropertyCache, 0, sizeof(HasOwnPropertyCache::Entry)) \
     macro(JSFixedArray_buffer, JSFixedArray::offsetOfData(), sizeof(EncodedJSValue)) \
-    
+    macro(TypedArrayPoisons, 0, sizeof(uintptr_t)) \
+
 #define FOR_EACH_NUMBERED_ABSTRACT_HEAP(macro) \
     macro(properties)
     

Modified: branches/safari-605-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -3459,7 +3459,14 @@
         }
 
         DFG_ASSERT(m_graph, m_node, isTypedView(m_node->arrayMode().typedArrayType()));
-        setStorage(caged(Gigacage::Primitive, m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector)));
+        LValue poisonedVector = m_out.loadPtr(cell, m_heaps.JSArrayBufferView_poisonedVector);
+#if ENABLE(POISON)
+        auto typedArrayType = m_node->arrayMode().typedArrayType();
+        LValue vector = m_out.bitXor(m_out.constIntPtr(JSArrayBufferView::poisonFor(typedArrayType)), poisonedVector);
+#else
+        LValue vector = poisonedVector;
+#endif
+        setStorage(caged(Gigacage::Primitive, vector));
     }
     
     void compileCheckArray()
@@ -3481,6 +3488,7 @@
 
         LBasicBlock simpleCase = m_out.newBlock();
         LBasicBlock wastefulCase = m_out.newBlock();
+        LBasicBlock notNull = m_out.newBlock();
         LBasicBlock continuation = m_out.newBlock();
         
         LValue mode = m_out.load32(basePtr, m_heaps.JSArrayBufferView_mode);
@@ -3494,13 +3502,27 @@
 
         m_out.jump(continuation);
 
-        m_out.appendTo(wastefulCase, continuation);
+        m_out.appendTo(wastefulCase, notNull);
 
-        LValue vectorPtr = cagedMayBeNull(
-            Gigacage::Primitive,
-            m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector));
+        LValue poisonedVector = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_poisonedVector);
+        ValueFromBlock nullVectorOut = m_out.anchor(poisonedVector);
+        m_out.branch(poisonedVector, unsure(notNull), unsure(continuation));
+
+        m_out.appendTo(notNull, continuation);
+
         LValue butterflyPtr = caged(Gigacage::JSValue, m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly));
         LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
+
+#if ENABLE(POISON)
+        LValue jsType = m_out.load8ZeroExt32(basePtr, m_heaps.JSCell_typeInfoType);
+        LValue typeIndex = m_out.sub(jsType, m_out.constInt32(FirstTypedArrayType));
+        LValue maskedTypeIndex = m_out.zeroExtPtr(m_out.bitAnd(typeIndex, m_out.constInt32(TypedArrayPoisonIndexMask)));
+        LValue poisonsBasePtr = m_out.constIntPtr(&g_typedArrayPoisons);
+        LValue poison = m_out.loadPtr(m_out.baseIndex(m_heaps.TypedArrayPoisons, poisonsBasePtr, maskedTypeIndex));
+        poisonedVector = m_out.bitXor(poisonedVector, poison);
+#endif
+        LValue vectorPtr = caged(Gigacage::Primitive, poisonedVector);
+
         // FIXME: This needs caging.
         // https://bugs.webkit.org/show_bug.cgi?id=175515
         LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
@@ -3510,7 +3532,7 @@
         m_out.jump(continuation);
         m_out.appendTo(continuation, lastNext);
 
-        setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, wastefulOut)));
+        setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, nullVectorOut, wastefulOut)));
     }
 
     void compileGetPrototypeOf()
@@ -5623,7 +5645,10 @@
             LValue fastResultValue =
                 allocateObject<JSArrayBufferView>(structure, m_out.intPtrZero, indexingMask, slowCase);
 
-            m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
+#if ENABLE(POISON)
+            storage = m_out.bitXor(m_out.constIntPtr(JSArrayBufferView::poisonFor(typedArrayType)), storage);
+#endif
+            m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_poisonedVector);
             m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
             m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
             
@@ -12713,24 +12738,6 @@
         return m_out.opaque(result);
     }
     
-    LValue cagedMayBeNull(Gigacage::Kind kind, LValue ptr)
-    {
-        LBasicBlock notNull = m_out.newBlock();
-        LBasicBlock continuation = m_out.newBlock();
-        
-        LBasicBlock lastNext = m_out.insertNewBlocksBefore(notNull);
-        
-        ValueFromBlock nullResult = m_out.anchor(ptr);
-        m_out.branch(ptr, unsure(notNull), unsure(continuation));
-        
-        m_out.appendTo(notNull, continuation);
-        ValueFromBlock notNullResult = m_out.anchor(caged(kind, ptr));
-        m_out.jump(continuation);
-        
-        m_out.appendTo(continuation, lastNext);
-        return m_out.phi(pointerType(), nullResult, notNullResult);
-    }
-    
     void buildSwitch(SwitchData* data, LType type, LValue switchValue)
     {
         ASSERT(type == pointerType() || type == Int32);
@@ -14932,7 +14939,7 @@
             unsure(isWasteful), unsure(continuation));
 
         LBasicBlock lastNext = m_out.appendTo(isWasteful, continuation);
-        LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_vector);
+        LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_poisonedVector);
         speculate(Uncountable, jsValueValue(vector), m_node, m_out.isZero64(vector));
         m_out.jump(continuation);
 

Modified: branches/safari-605-branch/Source/_javascript_Core/jit/IntrinsicEmitter.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/jit/IntrinsicEmitter.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/jit/IntrinsicEmitter.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -107,22 +107,31 @@
     case TypedArrayByteOffsetIntrinsic: {
         GPRReg scratchGPR = state.scratchGPR;
 
-        CCallHelpers::Jump emptyByteOffset = jit.branch32(
-            MacroAssembler::NotEqual,
+        CCallHelpers::Jump notEmptyByteOffset = jit.branch32(
+            MacroAssembler::Equal,
             MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
             TrustedImm32(WastefulTypedArray));
 
+        jit.move(TrustedImmPtr(0), valueGPR);
+        CCallHelpers::Jump done = jit.jump();
+
+        notEmptyByteOffset.link(&jit);
+
+        // We need to load the butterfly before the vector because baseGPR and valueGPR
+        // can be the same register.
         jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
-        jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), valueGPR);
+        jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfPoisonedVector()), valueGPR);
+        CCallHelpers::Jump nullVector = jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
+
+#if ENABLE(POISON)
+        auto typedArrayType = structure()->classInfo()->typedArrayStorageType;
+        jit.xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(typedArrayType)), valueGPR);
+#endif
         jit.loadPtr(MacroAssembler::Address(scratchGPR, Butterfly::offsetOfArrayBuffer()), scratchGPR);
         jit.loadPtr(MacroAssembler::Address(scratchGPR, ArrayBuffer::offsetOfData()), scratchGPR);
         jit.subPtr(scratchGPR, valueGPR);
 
-        CCallHelpers::Jump done = jit.jump();
-        
-        emptyByteOffset.link(&jit);
-        jit.move(TrustedImmPtr(0), valueGPR);
-        
+        nullVector.link(&jit);
         done.link(&jit);
         
         jit.boxInt32(valueGPR, valueRegs);

Modified: branches/safari-605-branch/Source/_javascript_Core/jit/JITPropertyAccess.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1457,9 +1457,9 @@
     return slowCases;
 }
 
-JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType typeArrayType)
 {
-    ASSERT(isInt(type));
+    ASSERT(isInt(typeArrayType));
     
     // The best way to test the array type is to use the classInfo. We need to do so without
     // clobbering the register that holds the indexing type, base, and property.
@@ -1480,22 +1480,26 @@
 #endif
     
     JumpList slowCases;
-    
+    JSType jsType = typeForTypedArrayType(typeArrayType);
+
     load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
-    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
+    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(jsType));
     slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
+    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), scratch);
+#if ENABLE(POISON)
+    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), scratch);
+#endif
     cageConditionally(Gigacage::Primitive, scratch, scratch2);
 
-    switch (elementSize(type)) {
+    switch (elementSize(typeArrayType)) {
     case 1:
-        if (JSC::isSigned(type))
+        if (JSC::isSigned(typeArrayType))
             load8SignedExtendTo32(BaseIndex(scratch, property, TimesOne), resultPayload);
         else
             load8(BaseIndex(scratch, property, TimesOne), resultPayload);
         break;
     case 2:
-        if (JSC::isSigned(type))
+        if (JSC::isSigned(typeArrayType))
             load16SignedExtendTo32(BaseIndex(scratch, property, TimesTwo), resultPayload);
         else
             load16(BaseIndex(scratch, property, TimesTwo), resultPayload);
@@ -1508,7 +1512,7 @@
     }
     
     Jump done;
-    if (type == TypeUint32) {
+    if (typeArrayType == TypeUint32) {
         Jump canBeInt = branch32(GreaterThanOrEqual, resultPayload, TrustedImm32(0));
         
         convertInt32ToDouble(resultPayload, fpRegT0);
@@ -1534,9 +1538,9 @@
     return slowCases;
 }
 
-JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType typeArrayType)
 {
-    ASSERT(isFloat(type));
+    ASSERT(isFloat(typeArrayType));
     
 #if USE(JSVALUE64)
     RegisterID base = regT0;
@@ -1554,14 +1558,18 @@
 #endif
     
     JumpList slowCases;
+    JSType jsType = typeForTypedArrayType(typeArrayType);
 
     load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
-    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
+    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(jsType));
     slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
+    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), scratch);
+#if ENABLE(POISON)
+    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), scratch);
+#endif
     cageConditionally(Gigacage::Primitive, scratch, scratch2);
     
-    switch (elementSize(type)) {
+    switch (elementSize(typeArrayType)) {
     case 4:
         loadFloat(BaseIndex(scratch, property, TimesFour), fpRegT0);
         convertFloatToDouble(fpRegT0, fpRegT0);
@@ -1588,10 +1596,10 @@
     return slowCases;    
 }
 
-JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType typeArrayType)
 {
     ArrayProfile* profile = ""
-    ASSERT(isInt(type));
+    ASSERT(isInt(typeArrayType));
     
     int value = currentInstruction[3].u.operand;
 
@@ -1610,9 +1618,10 @@
 #endif
     
     JumpList slowCases;
-    
+    JSType jsType = typeForTypedArrayType(typeArrayType);
+
     load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
-    badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
+    badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(jsType));
     Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
     emitArrayProfileOutOfBoundsSpecialCase(profile);
     slowCases.append(jump());
@@ -1628,12 +1637,15 @@
     
     // We would be loading this into base as in get_by_val, except that the slow
     // path expects the base to be unclobbered.
-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
+    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), lateScratch);
+#if ENABLE(POISON)
+    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), lateScratch);
+#endif
     cageConditionally(Gigacage::Primitive, lateScratch, lateScratch2);
     
-    if (isClamped(type)) {
-        ASSERT(elementSize(type) == 1);
-        ASSERT(!JSC::isSigned(type));
+    if (isClamped(typeArrayType)) {
+        ASSERT(elementSize(typeArrayType) == 1);
+        ASSERT(!JSC::isSigned(typeArrayType));
         Jump inBounds = branch32(BelowOrEqual, earlyScratch, TrustedImm32(0xff));
         Jump tooBig = branch32(GreaterThan, earlyScratch, TrustedImm32(0xff));
         xor32(earlyScratch, earlyScratch);
@@ -1644,7 +1656,7 @@
         inBounds.link(this);
     }
     
-    switch (elementSize(type)) {
+    switch (elementSize(typeArrayType)) {
     case 1:
         store8(earlyScratch, BaseIndex(lateScratch, property, TimesOne));
         break;
@@ -1661,10 +1673,10 @@
     return slowCases;
 }
 
-JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType type)
+JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, TypedArrayType typeArrayType)
 {
     ArrayProfile* profile = ""
-    ASSERT(isFloat(type));
+    ASSERT(isFloat(typeArrayType));
     
     int value = currentInstruction[3].u.operand;
 
@@ -1683,9 +1695,10 @@
 #endif
     
     JumpList slowCases;
-    
+    JSType jsType = typeForTypedArrayType(typeArrayType);
+
     load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
-    badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
+    badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(jsType));
     Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
     emitArrayProfileOutOfBoundsSpecialCase(profile);
     slowCases.append(jump());
@@ -1714,10 +1727,13 @@
     
     // We would be loading this into base as in get_by_val, except that the slow
     // path expects the base to be unclobbered.
-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
+    loadPtr(Address(base, JSArrayBufferView::offsetOfPoisonedVector()), lateScratch);
+#if ENABLE(POISON)
+    xorPtr(TrustedImmPtr(JSArrayBufferView::poisonFor(jsType)), lateScratch);
+#endif
     cageConditionally(Gigacage::Primitive, lateScratch, lateScratch2);
     
-    switch (elementSize(type)) {
+    switch (elementSize(typeArrayType)) {
     case 4:
         convertDoubleToFloat(fpRegT0, fpRegT0);
         storeFloat(fpRegT0, BaseIndex(lateScratch, property, TimesFour));

Modified: branches/safari-605-branch/Source/_javascript_Core/llint/LowLevelInterpreter.asm (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2018-01-31 09:09:31 UTC (rev 227886)
@@ -394,6 +394,7 @@
 
 const FirstArrayType = constexpr FirstTypedArrayType
 const NumberOfTypedArrayTypesExcludingDataView = constexpr NumberOfTypedArrayTypesExcludingDataView
+const TypedArrayPoisonIndexMask = constexpr TypedArrayPoisonIndexMask
 
 # Type flags constants.
 const MasqueradesAsUndefined = constexpr MasqueradesAsUndefined

Modified: branches/safari-605-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2018-01-31 09:09:31 UTC (rev 227886)
@@ -376,17 +376,34 @@
         end)
 end
 
-macro loadCaged(basePtr, mask, source, dest, scratch)
-    loadp source, dest
+macro uncage(basePtr, mask, ptr, scratch)
     if GIGACAGE_ENABLED and not C_LOOP
         loadp basePtr, scratch
         btpz scratch, .done
-        andp mask, dest
-        addp scratch, dest
+        andp mask, ptr
+        addp scratch, ptr
     .done:
     end
 end
 
+macro loadCaged(basePtr, mask, source, dest, scratch)
+    loadp source, dest
+    uncage(basePtr, mask, dest, scratch)
+end
+
+macro loadTypedArrayCaged(basePtr, mask, source, typeIndex, dest, scratch)
+    if POISON
+        andp TypedArrayPoisonIndexMask, typeIndex
+        leap _g_typedArrayPoisons, dest
+        loadp [dest, typeIndex, 8], dest
+        loadp source, scratch
+        xorp scratch, dest
+    else
+        loadp source, dest
+    end
+    uncage(basePtr, mask, dest, scratch)
+end
+
 macro loadVariable(operand, value)
     loadisFromInstruction(operand, value)
     loadq [cfr, value, 8], value
@@ -1541,9 +1558,9 @@
     biaeq t2, NumberOfTypedArrayTypesExcludingDataView, .opGetByValSlow
     
     # Sweet, now we know that we have a typed array. Do some basic things now.
-    loadCaged(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr PRIMITIVE_GIGACAGE_MASK, JSArrayBufferView::m_vector[t0], t3, t5)
     biaeq t1, JSArrayBufferView::m_length[t0], .opGetByValSlow
-    
+    loadTypedArrayCaged(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr PRIMITIVE_GIGACAGE_MASK, JSArrayBufferView::m_poisonedVector[t0], t2, t3, t5)
+
     # Now bisect through the various types:
     #    Int8ArrayType,
     #    Uint8ArrayType,

Modified: branches/safari-605-branch/Source/_javascript_Core/offlineasm/arm64.rb (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/offlineasm/arm64.rb	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/offlineasm/arm64.rb	2018-01-31 09:09:31 UTC (rev 227886)
@@ -275,6 +275,13 @@
                 else
                     newList << node
                 end
+            when "leai", "leap", "leaq"
+                labelRef = node.operands[0]
+                if labelRef.is_a? LabelReference
+                    newList << Instruction.new(codeOrigin, "globaladdr", [LabelReference.new(node.codeOrigin, labelRef.label), node.operands[1]])
+                else
+                    newList << node
+                end
             else
                 newList << node
             end

Modified: branches/safari-605-branch/Source/_javascript_Core/offlineasm/x86.rb (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/offlineasm/x86.rb	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/offlineasm/x86.rb	2018-01-31 09:09:31 UTC (rev 227886)
@@ -468,6 +468,11 @@
         $asm.puts "movq #{asmLabel}@GOTPCREL(%rip), #{dst.x86Operand(:ptr)}"
         "#{offset}(#{dst.x86Operand(kind)})"
     end
+    def x86AddressOperand(addressKind)
+        # FIXME: Implement this on platforms that aren't Mach-O.
+        # https://bugs.webkit.org/show_bug.cgi?id=175104
+        "#{asmLabel}@GOTPCREL(%rip)"
+    end
 end
 
 class LocalLabelReference
@@ -582,6 +587,15 @@
         end
     end
 
+    def emitX86Lea(src, dst, kind)
+        if src.is_a? LabelReference
+            $asm.puts "movq #{src.asmLabel}@GOTPCREL(%rip), #{dst.x86Operand(:ptr)}"
+            $asm.puts "mov#{x86Suffix(kind)} #{orderOperands(dst.x86Operand(kind), dst.x86Operand(kind))}"
+        else
+            $asm.puts "lea#{x86Suffix(kind)} #{orderOperands(src.x86AddressOperand(kind), dst.x86Operand(kind))}"
+        end
+    end
+
     def getImplicitOperandString
         isIntelSyntax ? "st(0), " : ""
     end
@@ -1542,9 +1556,9 @@
         when "bnz"
             $asm.puts "jnz #{operands[0].asmLabel}"
         when "leai"
-            $asm.puts "lea#{x86Suffix(:int)} #{orderOperands(operands[0].x86AddressOperand(:int), operands[1].x86Operand(:int))}"
+            emitX86Lea(operands[0], operands[1], :int)
         when "leap"
-            $asm.puts "lea#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86AddressOperand(:ptr), operands[1].x86Operand(:ptr))}"
+            emitX86Lea(operands[0], operands[1], :ptr)
         when "memfence"
             sp = RegisterID.new(nil, "sp")
             if isIntelSyntax

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/CagedBarrierPtr.h (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/CagedBarrierPtr.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/CagedBarrierPtr.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,8 +26,15 @@
 #pragma once
 
 #include "AuxiliaryBarrier.h"
+#include <type_traits>
 #include <wtf/CagedPtr.h>
 
+namespace WTF {
+
+template<typename Poison, typename T> struct PoisonedPtrTraits;
+
+} // namespace WTF
+
 namespace JSC {
 
 class JSCell;
@@ -35,7 +42,7 @@
 
 // This is a convenient combo of AuxiliaryBarrier and CagedPtr.
 
-template<Gigacage::Kind passedKind, typename T>
+template<Gigacage::Kind passedKind, typename T, typename PtrTraits = WTF::DumbPtrTraits<T>>
 class CagedBarrierPtr {
 public:
     static constexpr Gigacage::Kind kind = passedKind;
@@ -85,11 +92,11 @@
     T& operator[](IndexType index) const { return get()[index]; }
     
 private:
-    AuxiliaryBarrier<CagedPtr<kind, T>> m_barrier;
+    AuxiliaryBarrier<CagedPtr<kind, T, PtrTraits>> m_barrier;
 };
 
-template<Gigacage::Kind passedKind>
-class CagedBarrierPtr<passedKind, void> {
+template<Gigacage::Kind passedKind, typename PtrTraits>
+class CagedBarrierPtr<passedKind, void, PtrTraits> {
 public:
     static constexpr Gigacage::Kind kind = passedKind;
     typedef void Type;
@@ -132,7 +139,10 @@
     void setWithoutBarrier(U&& value) { m_barrier.setWithoutBarrier(std::forward<U>(value)); }
     
 private:
-    AuxiliaryBarrier<CagedPtr<kind, void>> m_barrier;
+    AuxiliaryBarrier<CagedPtr<kind, void, PtrTraits>> m_barrier;
 };
 
+template<typename Poison, Gigacage::Kind passedKind, typename T>
+using PoisonedCagedBarrierPtr = CagedBarrierPtr<passedKind, T, WTF::PoisonedPtrTraits<Poison, T>>;
+
 } // namespace JSC

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/JSArrayBufferView.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/JSArrayBufferView.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/JSArrayBufferView.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -132,7 +132,7 @@
     , m_mode(context.mode())
 {
     setButterflyWithIndexingMask(vm, context.butterfly(), WTF::computeIndexingMask(length()));
-    m_vector.setWithoutBarrier(context.vector());
+    m_poisonedVector.setWithoutBarrier(context.vector());
 }
 
 void JSArrayBufferView::finishCreation(VM& vm)
@@ -193,7 +193,7 @@
     JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell);
     ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray);
     if (thisObject->m_mode == OversizeTypedArray)
-        Gigacage::free(Gigacage::Primitive, thisObject->m_vector.get());
+        Gigacage::free(Gigacage::Primitive, thisObject->m_poisonedVector.get());
 }
 
 JSArrayBuffer* JSArrayBufferView::unsharedJSBuffer(ExecState* exec)
@@ -211,7 +211,7 @@
     RELEASE_ASSERT(hasArrayBuffer());
     RELEASE_ASSERT(!isShared());
     m_length = 0;
-    m_vector.clear();
+    m_poisonedVector.clear();
 }
 
 } // namespace JSC

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/JSArrayBufferView.h (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/JSArrayBufferView.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/JSArrayBufferView.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,12 +26,22 @@
 #pragma once
 
 #include "AuxiliaryBarrier.h"
+#include "CagedBarrierPtr.h"
+#include "JSCPoison.h"
 #include "JSObject.h"
+#include "TypedArrayType.h"
+#include <wtf/MathExtras.h>
 
 namespace JSC {
 
 class LLIntOffsetsExtractor;
 
+// Since we'll be indexing into the g_typedArrayPoisons array based on the TypedArray type,
+// we'll index mask the index value and round up to the array size to the next power of 2 to
+// ensure that we'll never be able to access beyond the bounds of this array.
+static constexpr uint32_t NumberOfTypedArrayPoisons = WTF::roundUpToPowerOfTwo(NumberOfTypedArrayTypes);
+static constexpr uint32_t TypedArrayPoisonIndexMask = NumberOfTypedArrayPoisons - 1;
+
 // This class serves two purposes:
 //
 // 1) It provides those parts of JSGenericTypedArrayView that don't depend
@@ -167,7 +177,7 @@
     bool isNeutered() { return hasArrayBuffer() && !vector(); }
     void neuter();
     
-    void* vector() const { return m_vector.getMayBeNull(); }
+    void* vector() const { return m_poisonedVector.getMayBeNull(); }
     
     unsigned byteOffset();
     unsigned length() const { return m_length; }
@@ -174,12 +184,23 @@
 
     DECLARE_EXPORT_INFO;
     
-    static ptrdiff_t offsetOfVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_vector); }
+    static ptrdiff_t offsetOfPoisonedVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_poisonedVector); }
     static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(JSArrayBufferView, m_length); }
     static ptrdiff_t offsetOfMode() { return OBJECT_OFFSETOF(JSArrayBufferView, m_mode); }
     
     static RefPtr<ArrayBufferView> toWrapped(VM&, JSValue);
 
+    static uintptr_t poisonFor(JSType type)
+    {
+        return g_typedArrayPoisons[(type - FirstTypedArrayType) & TypedArrayPoisonIndexMask];
+    }
+
+    static uintptr_t poisonFor(TypedArrayType typedArrayType)
+    {
+        ASSERT(isTypedView(typedArrayType));
+        return poisonFor(typeForTypedArrayType(typedArrayType));
+    }
+
 private:
     static void finalize(JSCell*);
 
@@ -190,7 +211,19 @@
 
     static String toStringName(const JSObject*, ExecState*);
 
-    CagedBarrierPtr<Gigacage::Primitive, void> m_vector;
+    class Poison {
+    public:
+        template<typename PoisonedType>
+        inline static uintptr_t key(const PoisonedType* poisonedPtr)
+        {
+            uintptr_t poisonedVectorAddress = bitwise_cast<uintptr_t>(poisonedPtr);
+            uintptr_t baseAddress = poisonedVectorAddress - OBJECT_OFFSETOF(JSArrayBufferView, m_poisonedVector);
+            JSArrayBufferView* thisObject = bitwise_cast<JSArrayBufferView*>(baseAddress);
+            return poisonFor(thisObject->type());
+        }
+    };
+
+    PoisonedCagedBarrierPtr<Poison, Gigacage::Primitive, void> m_poisonedVector;
     uint32_t m_length;
     TypedArrayMode m_mode;
 };

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/JSCPoison.cpp (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/JSCPoison.cpp	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/JSCPoison.cpp	2018-01-31 09:09:31 UTC (rev 227886)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "JSCPoison.h"
 
+#include "JSArrayBufferView.h"
 #include "Options.h"
 #include <mutex>
 #include <wtf/HashSet.h>
@@ -36,6 +37,8 @@
     uintptr_t POISON_KEY_NAME(poisonID);
 FOR_EACH_JSC_POISON(DEFINE_POISON)
 
+uintptr_t g_typedArrayPoisons[NumberOfTypedArrayPoisons];
+
 void initializePoison()
 {
     static std::once_flag initializeOnceFlag;
@@ -47,6 +50,9 @@
     POISON_KEY_NAME(poisonID) = makePoison();
 
         FOR_EACH_JSC_POISON(INITIALIZE_POISON)
+
+        for (uint32_t i = 0; i < NumberOfTypedArrayPoisons; ++i)
+            g_typedArrayPoisons[i] = makePoison();
     });
 }
 

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/JSCPoison.h (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/JSCPoison.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/JSCPoison.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -64,6 +64,8 @@
 FOR_EACH_JSC_POISON(DECLARE_POISON)
 #undef DECLARE_POISON
 
+extern "C" JS_EXPORTDATA uintptr_t g_typedArrayPoisons[];
+
 struct ClassInfo;
 
 using PoisonedClassInfoPtr = Poisoned<GlobalDataPoison, const ClassInfo*>;

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -504,7 +504,7 @@
 
     if (thisObject->m_mode == OversizeTypedArray)
         return Base::estimatedSize(thisObject) + thisObject->byteSize();
-    if (thisObject->m_mode == FastTypedArray && thisObject->m_vector)
+    if (thisObject->m_mode == FastTypedArray && thisObject->m_poisonedVector)
         return Base::estimatedSize(thisObject) + thisObject->byteSize();
 
     return Base::estimatedSize(thisObject);
@@ -517,7 +517,7 @@
     
     switch (thisObject->m_mode) {
     case FastTypedArray: {
-        if (void* vector = thisObject->m_vector.getMayBeNull())
+        if (void* vector = thisObject->m_poisonedVector.getMayBeNull())
             visitor.markAuxiliary(vector);
         break;
     }
@@ -585,7 +585,7 @@
     }
 
     thisObject->butterfly()->indexingHeader()->setArrayBuffer(buffer.get());
-    thisObject->m_vector.setWithoutBarrier(buffer->data());
+    thisObject->m_poisonedVector.setWithoutBarrier(buffer->data());
     WTF::storeStoreFence();
     thisObject->m_mode = WastefulTypedArray;
     heap->addReference(thisObject, buffer.get());

Modified: branches/safari-605-branch/Source/_javascript_Core/runtime/JSObject.h (227885 => 227886)


--- branches/safari-605-branch/Source/_javascript_Core/runtime/JSObject.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/_javascript_Core/runtime/JSObject.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -24,9 +24,9 @@
 
 #include "ArrayConventions.h"
 #include "ArrayStorage.h"
+#include "AuxiliaryBarrier.h"
 #include "Butterfly.h"
 #include "CPU.h"
-#include "CagedBarrierPtr.h"
 #include "CallFrame.h"
 #include "ClassInfo.h"
 #include "CustomGetterSetter.h"

Modified: branches/safari-605-branch/Source/WTF/ChangeLog (227885 => 227886)


--- branches/safari-605-branch/Source/WTF/ChangeLog	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/WTF/ChangeLog	2018-01-31 09:09:31 UTC (rev 227886)
@@ -1,3 +1,26 @@
+2018-01-31  Jason Marcell  <[email protected]>
+
+        Cherry-pick r227874. rdar://problem/37059537
+
+    2018-01-30  Mark Lam  <[email protected]>
+
+            Apply poisoning to TypedArray vector pointers.
+            https://bugs.webkit.org/show_bug.cgi?id=182155
+            <rdar://problem/36286266>
+
+            Reviewed by JF Bastien.
+
+            1. Added the ability to poison a CagedPtr.
+
+            2. Prevent CagedPtr from being implicitly instantiated, and add operator= methods
+               instead.  This is because implicitly instantiated CagedPtrs with a poisoned
+               trait may silently use a wrong poison value.
+
+            * wtf/CagedPtr.h:
+            (WTF::CagedPtr::CagedPtr):
+            (WTF::CagedPtr::get const):
+            (WTF::CagedPtr::operator=):
+
 2018-01-30  Jason Marcell  <[email protected]>
 
         Cherry-pick r227792. rdar://problem/37037861

Modified: branches/safari-605-branch/Source/WTF/wtf/CagedPtr.h (227885 => 227886)


--- branches/safari-605-branch/Source/WTF/wtf/CagedPtr.h	2018-01-31 09:09:26 UTC (rev 227885)
+++ branches/safari-605-branch/Source/WTF/wtf/CagedPtr.h	2018-01-31 09:09:31 UTC (rev 227886)
@@ -25,16 +25,20 @@
 
 #pragma once
 
+#include <wtf/DumbPtrTraits.h>
 #include <wtf/Gigacage.h>
 
 namespace WTF {
 
-template<Gigacage::Kind passedKind, typename T>
+template<Gigacage::Kind passedKind, typename T, typename PtrTraits = DumbPtrTraits<T>>
 class CagedPtr {
 public:
     static constexpr Gigacage::Kind kind = passedKind;
-    
-    CagedPtr(T* ptr = nullptr)
+
+    CagedPtr() : CagedPtr(nullptr) { }
+    CagedPtr(std::nullptr_t) : m_ptr(nullptr) { }
+
+    explicit CagedPtr(T* ptr)
         : m_ptr(ptr)
     {
     }
@@ -42,7 +46,7 @@
     T* get() const
     {
         ASSERT(m_ptr);
-        return Gigacage::caged(kind, m_ptr);
+        return Gigacage::caged(kind, PtrTraits::unwrap(m_ptr));
     }
     
     T* getMayBeNull() const
@@ -51,7 +55,19 @@
             return nullptr;
         return get();
     }
-    
+
+    CagedPtr& operator=(T* ptr)
+    {
+        m_ptr = ptr;
+        return *this;
+    }
+
+    CagedPtr& operator=(T*&& ptr)
+    {
+        m_ptr = WTFMove(ptr);
+        return *this;
+    }
+
     bool operator==(const CagedPtr& other) const
     {
         return getMayBeNull() == other.getMayBeNull();
@@ -74,15 +90,18 @@
     T& operator[](IndexType index) const { return get()[index]; }
     
 protected:
-    T* m_ptr;
+    typename PtrTraits::StorageType m_ptr;
 };
 
-template<Gigacage::Kind passedKind>
-class CagedPtr<passedKind, void> {
+template<Gigacage::Kind passedKind, typename PtrTraits>
+class CagedPtr<passedKind, void, PtrTraits> {
 public:
     static constexpr Gigacage::Kind kind = passedKind;
-    
-    CagedPtr(void* ptr = nullptr)
+
+    CagedPtr() : CagedPtr(nullptr) { }
+    CagedPtr(std::nullptr_t) : m_ptr(nullptr) { }
+
+    explicit CagedPtr(void* ptr)
         : m_ptr(ptr)
     {
     }
@@ -90,7 +109,7 @@
     void* get() const
     {
         ASSERT(m_ptr);
-        return Gigacage::caged(kind, m_ptr);
+        return Gigacage::caged(kind, PtrTraits::unwrap(m_ptr));
     }
     
     void* getMayBeNull() const
@@ -99,7 +118,13 @@
             return nullptr;
         return get();
     }
-    
+
+    CagedPtr& operator=(void* ptr)
+    {
+        m_ptr = ptr;
+        return *this;
+    }
+
     bool operator==(const CagedPtr& other) const
     {
         return getMayBeNull() == other.getMayBeNull();
@@ -116,7 +141,7 @@
     }
     
 protected:
-    void* m_ptr;
+    typename PtrTraits::StorageType m_ptr;
 };
 
 } // namespace WTF
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to