@@ -560,7 +560,7 @@ namespace Js
560560 }
561561 else if (jsArraySource)
562562 {
563- newArray->SetObject (jsArraySource, newArray->GetLength (), offset);
563+ newArray->SetObjectNoDetachCheck (jsArraySource, newArray->GetLength (), offset);
564564 OUTPUT_TRACE (TypedArrayPhase, _u (" Created a TypedArray from a JavaScript array source\n " ));
565565 }
566566
@@ -948,7 +948,7 @@ namespace Js
948948 {
949949 for (uint32 i = 0 ; i < sourceLength; i++)
950950 {
951- DirectSetItem (offset + i, source->DirectGetItem (i));
951+ DirectSetItemNoDetachCheck (offset + i, source->DirectGetItemNoDetachCheck (i));
952952 }
953953 }
954954 else
@@ -965,22 +965,58 @@ namespace Js
965965 DirectSetItem (offset + i, tmpArray->DirectGetItem (i));
966966 }
967967 }
968+ if (source->IsDetachedBuffer () || this ->IsDetachedBuffer ())
969+ {
970+ Throw::FatalInternalError ();
971+ }
968972 }
969973 }
970974
971- // Getting length from the source object can detach the typedarray, and thus set it's length as 0,
972- // this is observable because RangeError will be thrown instead of a TypeError further down the line
973- void TypedArrayBase::SetObject (RecyclableObject* source, uint32 targetLength, uint32 offset)
975+ uint32 TypedArrayBase::GetSourceLength (RecyclableObject* arraySource, uint32 targetLength, uint32 offset)
974976 {
975977 ScriptContext* scriptContext = GetScriptContext ();
976- uint32 sourceLength = JavascriptConversion::ToUInt32 (JavascriptOperators::OP_GetProperty (source , PropertyIds::length, scriptContext), scriptContext);
978+ uint32 sourceLength = JavascriptConversion::ToUInt32 (JavascriptOperators::OP_GetProperty (arraySource , PropertyIds::length, scriptContext), scriptContext);
977979 uint32 totalLength;
978980 if (UInt32Math::Add (offset, sourceLength, &totalLength) ||
979981 (totalLength > targetLength))
980982 {
981983 JavascriptError::ThrowRangeError (
982- GetScriptContext () , JSERR_InvalidTypedArrayLength);
984+ scriptContext , JSERR_InvalidTypedArrayLength);
983985 }
986+ return sourceLength;
987+ }
988+
989+ void TypedArrayBase::SetObjectNoDetachCheck (RecyclableObject* source, uint32 targetLength, uint32 offset)
990+ {
991+ ScriptContext* scriptContext = GetScriptContext ();
992+ uint32 sourceLength = GetSourceLength (source, targetLength, offset);
993+ Assert (!this ->IsDetachedBuffer ());
994+
995+ Var itemValue;
996+ Var undefinedValue = scriptContext->GetLibrary ()->GetUndefined ();
997+ for (uint32 i = 0 ; i < sourceLength; i++)
998+ {
999+ if (!source->GetItem (source, i, &itemValue, scriptContext))
1000+ {
1001+ itemValue = undefinedValue;
1002+ }
1003+ DirectSetItemNoDetachCheck (offset + i, itemValue);
1004+ }
1005+
1006+ if (this ->IsDetachedBuffer ())
1007+ {
1008+ // We cannot be detached when we are creating the typed array itself. Terminate if that happens.
1009+ Throw::FatalInternalError ();
1010+ }
1011+ }
1012+
1013+ // Getting length from the source object can detach the typedarray, and thus set it's length as 0,
1014+ // this is observable because RangeError will be thrown instead of a TypeError further down the line
1015+ void TypedArrayBase::SetObject (RecyclableObject* source, uint32 targetLength, uint32 offset)
1016+ {
1017+ ScriptContext* scriptContext = GetScriptContext ();
1018+ uint32 sourceLength = GetSourceLength (source, targetLength, offset);
1019+
9841020 Var itemValue;
9851021 Var undefinedValue = scriptContext->GetLibrary ()->GetUndefined ();
9861022 for (uint32 i = 0 ; i < sourceLength; i ++)
@@ -2668,6 +2704,70 @@ namespace Js
26682704 return BaseTypedDirectGetItem (index);
26692705 }
26702706
2707+ #define DIRECT_SET_NO_DETACH_CHECK (TypedArrayName, convertFn ) \
2708+ template <> \
2709+ inline BOOL TypedArrayName##::DirectSetItemNoDetachCheck(__in uint32 index, __in Var value) \
2710+ { \
2711+ return BaseTypedDirectSetItemNoDetachCheck (index, value, convertFn); \
2712+ }
2713+
2714+ DIRECT_SET_NO_DETACH_CHECK (Int8Array, JavascriptConversion::ToInt8);
2715+ DIRECT_SET_NO_DETACH_CHECK (Int8VirtualArray, JavascriptConversion::ToInt8);
2716+ DIRECT_SET_NO_DETACH_CHECK (Uint8Array, JavascriptConversion::ToUInt8);
2717+ DIRECT_SET_NO_DETACH_CHECK (Uint8VirtualArray, JavascriptConversion::ToUInt8);
2718+ DIRECT_SET_NO_DETACH_CHECK (Int16Array, JavascriptConversion::ToInt16);
2719+ DIRECT_SET_NO_DETACH_CHECK (Int16VirtualArray, JavascriptConversion::ToInt16);
2720+ DIRECT_SET_NO_DETACH_CHECK (Uint16Array, JavascriptConversion::ToUInt16);
2721+ DIRECT_SET_NO_DETACH_CHECK (Uint16VirtualArray, JavascriptConversion::ToUInt16);
2722+ DIRECT_SET_NO_DETACH_CHECK (Int32Array, JavascriptConversion::ToInt32);
2723+ DIRECT_SET_NO_DETACH_CHECK (Int32VirtualArray, JavascriptConversion::ToInt32);
2724+ DIRECT_SET_NO_DETACH_CHECK (Uint32Array, JavascriptConversion::ToUInt32);
2725+ DIRECT_SET_NO_DETACH_CHECK (Uint32VirtualArray, JavascriptConversion::ToUInt32);
2726+ DIRECT_SET_NO_DETACH_CHECK (Float32Array, JavascriptConversion::ToFloat);
2727+ DIRECT_SET_NO_DETACH_CHECK (Float32VirtualArray, JavascriptConversion::ToFloat);
2728+ DIRECT_SET_NO_DETACH_CHECK (Float64Array, JavascriptConversion::ToNumber);
2729+ DIRECT_SET_NO_DETACH_CHECK (Float64VirtualArray, JavascriptConversion::ToNumber);
2730+ DIRECT_SET_NO_DETACH_CHECK (Int64Array, JavascriptConversion::ToInt64);
2731+ DIRECT_SET_NO_DETACH_CHECK (Uint64Array, JavascriptConversion::ToUInt64);
2732+ DIRECT_SET_NO_DETACH_CHECK (Uint8ClampedArray, JavascriptConversion::ToUInt8Clamped);
2733+ DIRECT_SET_NO_DETACH_CHECK (Uint8ClampedVirtualArray, JavascriptConversion::ToUInt8Clamped);
2734+ DIRECT_SET_NO_DETACH_CHECK (BoolArray, JavascriptConversion::ToBool);
2735+
2736+ #define DIRECT_GET_NO_DETACH_CHECK (TypedArrayName ) \
2737+ template <> \
2738+ inline Var TypedArrayName##::DirectGetItemNoDetachCheck(__in uint32 index) \
2739+ { \
2740+ return BaseTypedDirectGetItemNoDetachCheck (index); \
2741+ }
2742+
2743+ #define DIRECT_GET_VAR_CHECK_NO_DETACH_CHECK (TypedArrayName ) \
2744+ template <> \
2745+ inline Var TypedArrayName##::DirectGetItemNoDetachCheck(__in uint32 index) \
2746+ { \
2747+ return DirectGetItemVarCheckNoDetachCheck (index); \
2748+ }
2749+
2750+ DIRECT_GET_NO_DETACH_CHECK (Int8Array);
2751+ DIRECT_GET_NO_DETACH_CHECK (Int8VirtualArray);
2752+ DIRECT_GET_NO_DETACH_CHECK (Uint8Array);
2753+ DIRECT_GET_NO_DETACH_CHECK (Uint8VirtualArray);
2754+ DIRECT_GET_NO_DETACH_CHECK (Int16Array);
2755+ DIRECT_GET_NO_DETACH_CHECK (Int16VirtualArray);
2756+ DIRECT_GET_NO_DETACH_CHECK (Uint16Array);
2757+ DIRECT_GET_NO_DETACH_CHECK (Uint16VirtualArray);
2758+ DIRECT_GET_NO_DETACH_CHECK (Int32Array);
2759+ DIRECT_GET_NO_DETACH_CHECK (Int32VirtualArray);
2760+ DIRECT_GET_NO_DETACH_CHECK (Uint32Array);
2761+ DIRECT_GET_NO_DETACH_CHECK (Uint32VirtualArray);
2762+ DIRECT_GET_NO_DETACH_CHECK (Int64Array);
2763+ DIRECT_GET_NO_DETACH_CHECK (Uint64Array);
2764+ DIRECT_GET_NO_DETACH_CHECK (Uint8ClampedArray);
2765+ DIRECT_GET_NO_DETACH_CHECK (Uint8ClampedVirtualArray);
2766+ DIRECT_GET_VAR_CHECK_NO_DETACH_CHECK (Float32Array);
2767+ DIRECT_GET_VAR_CHECK_NO_DETACH_CHECK (Float32VirtualArray);
2768+ DIRECT_GET_VAR_CHECK_NO_DETACH_CHECK (Float64Array);
2769+ DIRECT_GET_VAR_CHECK_NO_DETACH_CHECK (Float64VirtualArray);
2770+
26712771#define TypedArrayBeginStub (type ) \
26722772 Assert (GetArrayBuffer() || GetArrayBuffer()->GetBuffer ()); \
26732773 Assert (index < GetLength()); \
@@ -3196,6 +3296,14 @@ namespace Js
31963296 return GetLibrary ()->GetUndefined ();
31973297 }
31983298
3299+ template <>
3300+ inline Var BoolArray::DirectGetItemNoDetachCheck (__in uint32 index)
3301+ {
3302+ Assert ((index + 1 )* sizeof (bool ) + GetByteOffset () <= GetArrayBuffer ()->GetByteLength ());
3303+ bool * typedBuffer = (bool *)buffer;
3304+ return typedBuffer[index] ? GetLibrary ()->GetTrue () : GetLibrary ()->GetFalse ();
3305+ }
3306+
31993307 Var CharArray::Create (ArrayBufferBase* arrayBuffer, uint32 byteOffSet, uint32 mappedLength, JavascriptLibrary* javascriptLibrary)
32003308 {
32013309 CharArray* arr;
@@ -3285,6 +3393,16 @@ namespace Js
32853393 return FALSE ;
32863394 }
32873395
3396+ inline BOOL CharArray::DirectSetItemNoDetachCheck (__in uint32 index, __in Js::Var value)
3397+ {
3398+ return DirectSetItem (index, value);
3399+ }
3400+
3401+ inline Var CharArray::DirectGetItemNoDetachCheck (__in uint32 index)
3402+ {
3403+ return DirectGetItem (index);
3404+ }
3405+
32883406 Var CharArray::TypedAdd (__in uint32 index, Var second)
32893407 {
32903408 JavascriptError::ThrowTypeError (GetScriptContext (), JSERR_InvalidOperationOnTypedArray);
0 commit comments