Skip to content

Commit

Permalink
[CVE-2018-8466] Edge - Chakra: JIT: BailOutOnInvalidatedArrayHeadSegm…
Browse files Browse the repository at this point in the history
…ent check bypass - Google, Inc.
  • Loading branch information
rajatd authored and MikeHolman committed Sep 11, 2018
1 parent 9836062 commit a404dec
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 8 deletions.
2 changes: 2 additions & 0 deletions lib/Backend/Lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14707,6 +14707,8 @@ IR::RegOpnd *Lowerer::GenerateArrayTest(
{
// Only DynamicObject is allowed (DynamicObject vtable is ensured) because some object types have special handling for
// index properties - arguments object, string object, external object, etc.
// If other object types are also allowed in the future, corresponding changes will have to made to
// JavascriptArray::Jit_TryGetArrayForObjectWithArray as well.
GenerateObjectTypeTest(baseOpnd, insertBeforeInstr, isNotObjectLabel);
GenerateObjectHeaderInliningTest(baseOpnd, isNotArrayLabel, insertBeforeInstr);
arrayOpnd = LoadObjectArray(baseOpnd, insertBeforeInstr);
Expand Down
69 changes: 62 additions & 7 deletions lib/Runtime/Library/JavascriptArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,67 @@ using namespace Js;
return scriptContext->GetLibrary()->GetArrayType();
}

JavascriptArray *JavascriptArray::GetArrayForArrayOrObjectWithArray(const Var var)
JavascriptArray *JavascriptArray::Jit_GetArrayForArrayOrObjectWithArray(const Var var)
{
bool isObjectWithArray;
TypeId arrayTypeId;
return GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray, &arrayTypeId);
return Jit_GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray);
}

JavascriptArray *JavascriptArray::Jit_GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef)
{
Assert(var);
Assert(isObjectWithArrayRef);

*isObjectWithArrayRef = false;

if (!RecyclableObject::Is(var))
{
return nullptr;
}

JavascriptArray *array = nullptr;
INT_PTR vtable = VirtualTableInfoBase::GetVirtualTable(var);
if (!Jit_TryGetArrayForObjectWithArray(var, isObjectWithArrayRef, &vtable, &array))
{
return nullptr;
}

if (vtable != VirtualTableInfo<JavascriptArray>::Address &&
vtable != VirtualTableInfo<CrossSiteObject<JavascriptArray>>::Address &&
vtable != VirtualTableInfo<JavascriptNativeIntArray>::Address &&
vtable != VirtualTableInfo<CrossSiteObject<JavascriptNativeIntArray>>::Address &&
vtable != VirtualTableInfo<JavascriptNativeFloatArray>::Address &&
vtable != VirtualTableInfo<CrossSiteObject<JavascriptNativeFloatArray>>::Address)
{
return nullptr;
}

if (!array)
{
array = FromVar(var);
}
return array;
}

bool JavascriptArray::Jit_TryGetArrayForObjectWithArray(const Var var, bool *const isObjectWithArrayRef, INT_PTR* pVTable, JavascriptArray** pArray)
{
Assert(isObjectWithArrayRef);
Assert(pVTable);
Assert(pArray);

if (*pVTable == VirtualTableInfo<DynamicObject>::Address ||
*pVTable == VirtualTableInfo<CrossSiteObject<DynamicObject>>::Address)
{
ArrayObject* objectArray = DynamicObject::FromVar(var)->GetObjectArray();
*pArray = (objectArray && Is(objectArray)) ? FromVar(objectArray) : nullptr;
if (!(*pArray))
{
return false;
}
*isObjectWithArrayRef = true;
*pVTable = VirtualTableInfoBase::GetVirtualTable(*pArray);
}
return true;
}

JavascriptArray *JavascriptArray::GetArrayForArrayOrObjectWithArray(
Expand Down Expand Up @@ -664,7 +720,7 @@ using namespace Js;
const SparseArraySegmentBase *JavascriptArray::Jit_GetArrayHeadSegmentForArrayOrObjectWithArray(const Var var)
{
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Array_Jit_GetArrayHeadSegmentForArrayOrObjectWithArray);
JavascriptArray *const array = GetArrayForArrayOrObjectWithArray(var);
JavascriptArray *const array = Jit_GetArrayForArrayOrObjectWithArray(var);
return array ? array->head : nullptr;
JIT_HELPER_END(Array_Jit_GetArrayHeadSegmentForArrayOrObjectWithArray);
}
Expand Down Expand Up @@ -701,8 +757,7 @@ using namespace Js;
{
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Array_Jit_GetArrayLength);
bool isObjectWithArray;
TypeId arrayTypeId;
JavascriptArray *const array = GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray, &arrayTypeId);
JavascriptArray *const array = Jit_GetArrayForArrayOrObjectWithArray(var, &isObjectWithArray);
return array && !isObjectWithArray ? array->GetLength() : 0;
JIT_HELPER_END(Array_Jit_GetArrayLength);
}
Expand All @@ -717,7 +772,7 @@ using namespace Js;
DynamicObjectFlags JavascriptArray::Jit_GetArrayFlagsForArrayOrObjectWithArray(const Var var)
{
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Array_Jit_GetArrayFlagsForArrayOrObjectWithArray);
JavascriptArray *const array = GetArrayForArrayOrObjectWithArray(var);
JavascriptArray *const array = Jit_GetArrayForArrayOrObjectWithArray(var);
return array && array->UsesObjectArrayOrFlagsAsFlags() ? array->GetFlags() : DynamicObjectFlags::None;
JIT_HELPER_END(Array_Jit_GetArrayFlagsForArrayOrObjectWithArray);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/Runtime/Library/JavascriptArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,9 @@ namespace Js
void LinkSegmentsCommon(SparseArraySegmentBase* prev, SparseArraySegmentBase* current);

public:
static JavascriptArray *GetArrayForArrayOrObjectWithArray(const Var var);
static JavascriptArray *Jit_GetArrayForArrayOrObjectWithArray(const Var var);
static JavascriptArray *Jit_GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef);
static bool Jit_TryGetArrayForObjectWithArray(const Var var, bool *const isObjectWithArrayRef, INT_PTR* vtable, JavascriptArray ** array);
static JavascriptArray *GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef, TypeId *const arrayTypeIdRef);
static const SparseArraySegmentBase *Jit_GetArrayHeadSegmentForArrayOrObjectWithArray(const Var var);
static uint32 Jit_GetArrayHeadSegmentLength(const SparseArraySegmentBase *const headSegment);
Expand Down

0 comments on commit a404dec

Please sign in to comment.