Skip to content

Commit a404dec

Browse files
rajatdMikeHolman
authored andcommitted
[CVE-2018-8466] Edge - Chakra: JIT: BailOutOnInvalidatedArrayHeadSegment check bypass - Google, Inc.
1 parent 9836062 commit a404dec

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

lib/Backend/Lower.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14707,6 +14707,8 @@ IR::RegOpnd *Lowerer::GenerateArrayTest(
1470714707
{
1470814708
// Only DynamicObject is allowed (DynamicObject vtable is ensured) because some object types have special handling for
1470914709
// index properties - arguments object, string object, external object, etc.
14710+
// If other object types are also allowed in the future, corresponding changes will have to made to
14711+
// JavascriptArray::Jit_TryGetArrayForObjectWithArray as well.
1471014712
GenerateObjectTypeTest(baseOpnd, insertBeforeInstr, isNotObjectLabel);
1471114713
GenerateObjectHeaderInliningTest(baseOpnd, isNotArrayLabel, insertBeforeInstr);
1471214714
arrayOpnd = LoadObjectArray(baseOpnd, insertBeforeInstr);

lib/Runtime/Library/JavascriptArray.cpp

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -596,11 +596,67 @@ using namespace Js;
596596
return scriptContext->GetLibrary()->GetArrayType();
597597
}
598598

599-
JavascriptArray *JavascriptArray::GetArrayForArrayOrObjectWithArray(const Var var)
599+
JavascriptArray *JavascriptArray::Jit_GetArrayForArrayOrObjectWithArray(const Var var)
600600
{
601601
bool isObjectWithArray;
602-
TypeId arrayTypeId;
603-
return GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray, &arrayTypeId);
602+
return Jit_GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray);
603+
}
604+
605+
JavascriptArray *JavascriptArray::Jit_GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef)
606+
{
607+
Assert(var);
608+
Assert(isObjectWithArrayRef);
609+
610+
*isObjectWithArrayRef = false;
611+
612+
if (!RecyclableObject::Is(var))
613+
{
614+
return nullptr;
615+
}
616+
617+
JavascriptArray *array = nullptr;
618+
INT_PTR vtable = VirtualTableInfoBase::GetVirtualTable(var);
619+
if (!Jit_TryGetArrayForObjectWithArray(var, isObjectWithArrayRef, &vtable, &array))
620+
{
621+
return nullptr;
622+
}
623+
624+
if (vtable != VirtualTableInfo<JavascriptArray>::Address &&
625+
vtable != VirtualTableInfo<CrossSiteObject<JavascriptArray>>::Address &&
626+
vtable != VirtualTableInfo<JavascriptNativeIntArray>::Address &&
627+
vtable != VirtualTableInfo<CrossSiteObject<JavascriptNativeIntArray>>::Address &&
628+
vtable != VirtualTableInfo<JavascriptNativeFloatArray>::Address &&
629+
vtable != VirtualTableInfo<CrossSiteObject<JavascriptNativeFloatArray>>::Address)
630+
{
631+
return nullptr;
632+
}
633+
634+
if (!array)
635+
{
636+
array = FromVar(var);
637+
}
638+
return array;
639+
}
640+
641+
bool JavascriptArray::Jit_TryGetArrayForObjectWithArray(const Var var, bool *const isObjectWithArrayRef, INT_PTR* pVTable, JavascriptArray** pArray)
642+
{
643+
Assert(isObjectWithArrayRef);
644+
Assert(pVTable);
645+
Assert(pArray);
646+
647+
if (*pVTable == VirtualTableInfo<DynamicObject>::Address ||
648+
*pVTable == VirtualTableInfo<CrossSiteObject<DynamicObject>>::Address)
649+
{
650+
ArrayObject* objectArray = DynamicObject::FromVar(var)->GetObjectArray();
651+
*pArray = (objectArray && Is(objectArray)) ? FromVar(objectArray) : nullptr;
652+
if (!(*pArray))
653+
{
654+
return false;
655+
}
656+
*isObjectWithArrayRef = true;
657+
*pVTable = VirtualTableInfoBase::GetVirtualTable(*pArray);
658+
}
659+
return true;
604660
}
605661

606662
JavascriptArray *JavascriptArray::GetArrayForArrayOrObjectWithArray(
@@ -664,7 +720,7 @@ using namespace Js;
664720
const SparseArraySegmentBase *JavascriptArray::Jit_GetArrayHeadSegmentForArrayOrObjectWithArray(const Var var)
665721
{
666722
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Array_Jit_GetArrayHeadSegmentForArrayOrObjectWithArray);
667-
JavascriptArray *const array = GetArrayForArrayOrObjectWithArray(var);
723+
JavascriptArray *const array = Jit_GetArrayForArrayOrObjectWithArray(var);
668724
return array ? array->head : nullptr;
669725
JIT_HELPER_END(Array_Jit_GetArrayHeadSegmentForArrayOrObjectWithArray);
670726
}
@@ -701,8 +757,7 @@ using namespace Js;
701757
{
702758
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Array_Jit_GetArrayLength);
703759
bool isObjectWithArray;
704-
TypeId arrayTypeId;
705-
JavascriptArray *const array = GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray, &arrayTypeId);
760+
JavascriptArray *const array = Jit_GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray);
706761
return array && !isObjectWithArray ? array->GetLength() : 0;
707762
JIT_HELPER_END(Array_Jit_GetArrayLength);
708763
}
@@ -717,7 +772,7 @@ using namespace Js;
717772
DynamicObjectFlags JavascriptArray::Jit_GetArrayFlagsForArrayOrObjectWithArray(const Var var)
718773
{
719774
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Array_Jit_GetArrayFlagsForArrayOrObjectWithArray);
720-
JavascriptArray *const array = GetArrayForArrayOrObjectWithArray(var);
775+
JavascriptArray *const array = Jit_GetArrayForArrayOrObjectWithArray(var);
721776
return array && array->UsesObjectArrayOrFlagsAsFlags() ? array->GetFlags() : DynamicObjectFlags::None;
722777
JIT_HELPER_END(Array_Jit_GetArrayFlagsForArrayOrObjectWithArray);
723778
}

lib/Runtime/Library/JavascriptArray.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,9 @@ namespace Js
439439
void LinkSegmentsCommon(SparseArraySegmentBase* prev, SparseArraySegmentBase* current);
440440

441441
public:
442-
static JavascriptArray *GetArrayForArrayOrObjectWithArray(const Var var);
442+
static JavascriptArray *Jit_GetArrayForArrayOrObjectWithArray(const Var var);
443+
static JavascriptArray *Jit_GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef);
444+
static bool Jit_TryGetArrayForObjectWithArray(const Var var, bool *const isObjectWithArrayRef, INT_PTR* vtable, JavascriptArray ** array);
443445
static JavascriptArray *GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef, TypeId *const arrayTypeIdRef);
444446
static const SparseArraySegmentBase *Jit_GetArrayHeadSegmentForArrayOrObjectWithArray(const Var var);
445447
static uint32 Jit_GetArrayHeadSegmentLength(const SparseArraySegmentBase *const headSegment);

0 commit comments

Comments
 (0)