Skip to content

Commit 91bb6d6

Browse files
rajatdaneeshdk
authored andcommitted
[CVE-2018-8372] Edge - Report a type confusion bug in Edge - 360Vulcan
1 parent 765bcd2 commit 91bb6d6

23 files changed

+280
-38
lines changed

lib/Backend/BackwardPass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4907,8 +4907,8 @@ BackwardPass::UpdateArrayBailOutKind(IR::Instr *const instr)
49074907
}
49084908

49094909
IR::BailOutKind includeBailOutKinds = IR::BailOutInvalid;
4910-
if(!baseValueType.IsNotNativeArray() &&
4911-
(!baseValueType.IsLikelyNativeArray() || !instr->GetSrc1()->IsInt32()) &&
4910+
if (!baseValueType.IsNotNativeArray() &&
4911+
(!baseValueType.IsLikelyNativeArray() || instr->GetSrc1()->IsVar()) &&
49124912
!currentBlock->noImplicitCallNativeArrayUses->IsEmpty() &&
49134913
!(instr->GetBailOutKind() & IR::BailOutOnArrayAccessHelperCall))
49144914
{

lib/Backend/Lower.cpp

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4207,7 +4207,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
42074207
{
42084208
// Ensure we don't write missingItems past allocation size
42094209
Assert(offsetStart + missingItemIndex * sizeOfElement <= maxAllocationSize);
4210-
GenerateMemInit(headOpnd, offsetStart + missingItemIndex * sizeOfElement, GetMissingItemOpnd(missingItemType, func), instr, true /*isZeroed*/);
4210+
GenerateMemInit(headOpnd, offsetStart + missingItemIndex * sizeOfElement, GetMissingItemOpndForAssignment(missingItemType, func), instr, true /*isZeroed*/);
42114211
missingItemIndex++;
42124212
}
42134213

@@ -10802,7 +10802,7 @@ Lowerer::LowerStElemC(IR::Instr * stElem)
1080210802
IR::Opnd* missingElementOpnd = GetMissingItemOpnd(stElem->GetSrc1()->GetType(), m_func);
1080310803
if (!stElem->GetSrc1()->IsEqual(missingElementOpnd))
1080410804
{
10805-
InsertCompareBranch(stElem->GetSrc1(), missingElementOpnd , Js::OpCode::BrEq_A, labelBailOut, stElem, true);
10805+
InsertMissingItemCompareBranch(stElem->GetSrc1(), Js::OpCode::BrEq_A, labelBailOut, stElem);
1080610806
}
1080710807
else
1080810808
{
@@ -11858,7 +11858,7 @@ Lowerer::GenerateHelperToArrayPopFastPath(IR::Instr * instr, IR::LabelInstr * do
1185811858
if(retInstr->GetDst())
1185911859
{
1186011860
//Do this check only for native arrays with Dst. For Var arrays, this is taken care in the Runtime helper itself.
11861-
InsertCompareBranch(GetMissingItemOpnd(retInstr->GetDst()->GetType(), m_func), retInstr->GetDst(), Js::OpCode::BrNeq_A, doneLabel, bailOutLabelHelper);
11861+
InsertMissingItemCompareBranch(retInstr->GetDst(), Js::OpCode::BrNeq_A, doneLabel, bailOutLabelHelper);
1186211862
}
1186311863
else
1186411864
{
@@ -16459,13 +16459,11 @@ Lowerer::GenerateFastElemIIntIndexCommon(
1645916459
Assert(instr->m_opcode != Js::OpCode::InlineArrayPush || bailOutLabelInstr);
1646016460

1646116461
// Check for a write of the MissingItem value.
16462-
InsertCompareBranch(
16462+
InsertMissingItemCompareBranch(
1646316463
element,
16464-
GetMissingItemOpnd(elementType, m_func),
1646516464
Js::OpCode::BrEq_A,
1646616465
instr->m_opcode == Js::OpCode::InlineArrayPush ? bailOutLabelInstr : labelCantUseArray,
16467-
instr,
16468-
true);
16466+
instr);
1646916467
}
1647016468

1647116469
if(!headSegmentOpnd)
@@ -16985,17 +16983,15 @@ Lowerer::GenerateFastElemIIntIndexCommon(
1698516983
//If the array has missing values, check for one
1698616984
if (!baseValueType.HasNoMissingValues())
1698716985
{
16988-
InsertCompareBranch(
16986+
InsertMissingItemCompareBranch(
1698916987
dst,
16990-
GetMissingItemOpnd(indirType, m_func),
1699116988
Js::OpCode::BrEq_A,
1699216989
bailOutLabelInstr,
16993-
instr,
16994-
true);
16990+
instr);
1699516991
}
1699616992
}
1699716993
// MOV [head + offset], missing
16998-
InsertMove(indirOpnd, GetMissingItemOpnd(indirType, m_func), instr);
16994+
InsertMove(indirOpnd, GetMissingItemOpndForAssignment(indirType, m_func), instr);
1699916995

1700016996
IR::Opnd *newLengthOpnd;
1700116997
IR::AutoReuseOpnd autoReuseNewLengthOpnd;
@@ -17276,6 +17272,22 @@ Lowerer::GenerateFastElemIIntIndexCommon(
1727617272
return indirOpnd;
1727717273
}
1727817274

17275+
IR::BranchInstr*
17276+
Lowerer::InsertMissingItemCompareBranch(IR::Opnd* compareSrc, Js::OpCode opcode, IR::LabelInstr* target, IR::Instr* insertBeforeInstr)
17277+
{
17278+
IR::Opnd* missingItemOpnd = GetMissingItemOpndForCompare(compareSrc->GetType(), m_func);
17279+
if (compareSrc->IsFloat64())
17280+
{
17281+
Assert(compareSrc->IsRegOpnd() || compareSrc->IsIndirOpnd());
17282+
return m_lowererMD.InsertMissingItemCompareBranch(compareSrc, missingItemOpnd, opcode, target, insertBeforeInstr);
17283+
}
17284+
else
17285+
{
17286+
Assert(compareSrc->IsInt32() || compareSrc->IsVar());
17287+
return InsertCompareBranch(missingItemOpnd, compareSrc, opcode, target, insertBeforeInstr, true);
17288+
}
17289+
}
17290+
1727917291
IR::RegOpnd *
1728017292
Lowerer::GenerateUntagVar(IR::RegOpnd * opnd, IR::LabelInstr * labelFail, IR::Instr * insertBeforeInstr, bool generateTagCheck)
1728117293
{
@@ -17836,13 +17848,11 @@ Lowerer::GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef)
1783617848
{
1783717849
// TEST dst, dst
1783817850
// JEQ $helper | JNE $fallthrough
17839-
InsertCompareBranch(
17851+
InsertMissingItemCompareBranch(
1784017852
dst,
17841-
GetMissingItemOpnd(dst->GetType(), m_func),
1784217853
needObjectTest ? Js::OpCode::BrEq_A : Js::OpCode::BrNeq_A,
1784317854
needObjectTest ? labelHelper : labelFallThru,
17844-
ldElem,
17845-
true);
17855+
ldElem);
1784617856

1784717857
if (isNativeArrayLoad)
1784817858
{
@@ -17928,7 +17938,7 @@ Lowerer::GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef)
1792817938
labelMissingNative = IR::LabelInstr::New(Js::OpCode::Label, m_func, true);
1792917939
}
1793017940

17931-
InsertCompareBranch(GetMissingItemOpnd(ldElem->GetDst()->GetType(), m_func), ldElem->GetDst(), Js::OpCode::BrEq_A, labelMissingNative, insertBeforeInstr, true);
17941+
InsertMissingItemCompareBranch(ldElem->GetDst(), Js::OpCode::BrEq_A, labelMissingNative, insertBeforeInstr);
1793217942
}
1793317943
InsertBranch(Js::OpCode::Br, labelFallThru, insertBeforeInstr);
1793417944
if(labelMissingNative)
@@ -17960,7 +17970,7 @@ Lowerer::GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef)
1796017970
{
1796117971
if(!emitBailout)
1796217972
{
17963-
InsertCompareBranch(GetMissingItemOpnd(ldElem->GetDst()->GetType(), m_func), ldElem->GetDst(), Js::OpCode::BrEq_A, labelBailOut, insertBeforeInstr, true);
17973+
InsertMissingItemCompareBranch(ldElem->GetDst(), Js::OpCode::BrEq_A, labelBailOut, insertBeforeInstr);
1796417974
}
1796517975

1796617976
InsertBranch(Js::OpCode::Br, labelFallThru, insertBeforeInstr);
@@ -17990,8 +18000,48 @@ Lowerer::GetMissingItemOpnd(IRType type, Func *func)
1799018000
{
1799118001
return IR::IntConstOpnd::New(Js::JavascriptNativeIntArray::MissingItem, TyInt32, func, true);
1799218002
}
17993-
Assert(type == TyFloat64);
17994-
return IR::MemRefOpnd::New(func->GetThreadContextInfo()->GetNativeFloatArrayMissingItemAddr(), TyFloat64, func);
18003+
AssertMsg(false, "Only expecting TyVar and TyInt32 in Lowerer::GetMissingItemOpnd");
18004+
__assume(false);
18005+
}
18006+
18007+
IR::Opnd*
18008+
Lowerer::GetMissingItemOpndForAssignment(IRType type, Func *func)
18009+
{
18010+
switch (type)
18011+
{
18012+
case TyVar:
18013+
case TyInt32:
18014+
return GetMissingItemOpnd(type, func);
18015+
18016+
case TyFloat64:
18017+
return IR::MemRefOpnd::New(func->GetThreadContextInfo()->GetNativeFloatArrayMissingItemAddr(), TyFloat64, func);
18018+
18019+
default:
18020+
AnalysisAssertMsg(false, "Unexpected type in Lowerer::GetMissingItemOpndForAssignment");
18021+
__assume(false);
18022+
}
18023+
}
18024+
18025+
IR::Opnd *
18026+
Lowerer::GetMissingItemOpndForCompare(IRType type, Func *func)
18027+
{
18028+
switch (type)
18029+
{
18030+
case TyVar:
18031+
case TyInt32:
18032+
return GetMissingItemOpnd(type, func);
18033+
18034+
case TyFloat64:
18035+
#if TARGET_64
18036+
return IR::MemRefOpnd::New(func->GetThreadContextInfo()->GetNativeFloatArrayMissingItemAddr(), TyUint64, func);
18037+
#else
18038+
return IR::MemRefOpnd::New(func->GetThreadContextInfo()->GetNativeFloatArrayMissingItemAddr(), TyUint32, func);
18039+
#endif
18040+
18041+
default:
18042+
AnalysisAssertMsg(false, "Unexpected type in Lowerer::GetMissingItemOpndForCompare");
18043+
__assume(false);
18044+
}
1799518045
}
1799618046

1799718047
bool
@@ -18631,13 +18681,11 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef)
1863118681
//
1863218682
// cmp [segment + index], Js::SparseArraySegment::MissingValue
1863318683
// je $helper
18634-
InsertCompareBranch(
18684+
InsertMissingItemCompareBranch(
1863518685
indirOpnd,
18636-
GetMissingItemOpnd(src->GetType(), m_func),
1863718686
Js::OpCode::BrEq_A,
1863818687
labelHelper,
18639-
stElem,
18640-
true);
18688+
stElem);
1864118689
}
1864218690
else
1864318691
{
@@ -28023,6 +28071,13 @@ Lowerer::AddBailoutToHelperCallInstr(IR::Instr * helperCallInstr, BailOutInfo *
2802328071
return helperCallInstr;
2802428072
}
2802528073

28074+
void
28075+
Lowerer::InsertAndLegalize(IR::Instr * instr, IR::Instr* insertBeforeInstr)
28076+
{
28077+
insertBeforeInstr->InsertBefore(instr);
28078+
LowererMD::Legalize(instr);
28079+
}
28080+
2802628081
#if DBG
2802728082
void
2802828083
Lowerer::LegalizeVerifyRange(IR::Instr * instrStart, IR::Instr * instrLast)

lib/Backend/Lower.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ class Lowerer
417417
public:
418418
static IR::HelperCallOpnd* CreateHelperCallOpnd(IR::JnHelperMethod helperMethod, int helperArgCount, Func* func);
419419
static IR::Opnd * GetMissingItemOpnd(IRType type, Func *func);
420+
static IR::Opnd * GetMissingItemOpndForAssignment(IRType type, Func *func);
421+
static IR::Opnd * GetMissingItemOpndForCompare(IRType type, Func *func);
420422
static IR::Opnd * GetImplicitCallFlagsOpnd(Func * func);
421423
inline static IR::IntConstOpnd* MakeCallInfoConst(ushort flags, int32 argCount, Func* func) {
422424
argCount = Js::CallInfo::GetArgCountWithoutExtraArgs((Js::CallFlags)flags, (uint16)argCount);
@@ -430,6 +432,7 @@ class Lowerer
430432
return IR::IntConstOpnd::New(argCount | (flags << 24), TyMachReg, func, true);
431433
#endif
432434
}
435+
static void InsertAndLegalize(IR::Instr * instr, IR::Instr* insertBeforeInstr);
433436
private:
434437
IR::IndirOpnd* GenerateFastElemICommon(
435438
_In_ IR::Instr* elemInstr,
@@ -516,6 +519,7 @@ class Lowerer
516519
_Inout_ IR::RegOpnd** taggedTypeOpnd);
517520

518521
void GenerateFastIsInSymbolOrStringIndex(IR::Instr * instrInsert, IR::RegOpnd *indexOpnd, IR::RegOpnd *baseOpnd, IR::Opnd *dest, uint32 inlineCacheOffset, const uint32 hitRateOffset, IR::LabelInstr * labelHelper, IR::LabelInstr * labelDone);
522+
IR::BranchInstr* InsertMissingItemCompareBranch(IR::Opnd* compareSrc, Js::OpCode opcode, IR::LabelInstr* target, IR::Instr* insertBeforeInstr);
519523
bool GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef);
520524
bool GenerateFastStElemI(IR::Instr *& StElem, bool *instrIsInHelperBlockRef);
521525
bool GenerateFastLdLen(IR::Instr *ldLen, bool *instrIsInHelperBlockRef);

lib/Backend/LowerMDShared.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8624,4 +8624,10 @@ LowererMD::InsertCmovCC(const Js::OpCode opCode, IR::Opnd * dst, IR::Opnd* src1,
86248624
LowererMD::Legalize(instr);
86258625

86268626
return instr;
8627+
}
8628+
8629+
IR::BranchInstr*
8630+
LowererMD::InsertMissingItemCompareBranch(IR::Opnd* compareSrc, IR::Opnd* missingItemOpnd, Js::OpCode opcode, IR::LabelInstr* target, IR::Instr* insertBeforeInstr)
8631+
{
8632+
return this->lowererMDArch.InsertMissingItemCompareBranch(compareSrc, missingItemOpnd, opcode, target, insertBeforeInstr);
86278633
}

lib/Backend/LowerMDShared.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ class LowererMD
223223
void EmitLoadFloatFromNumber(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr);
224224
void EmitLoadFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr, IR::Instr * instrBailOut = nullptr, IR::LabelInstr * labelBailOut = nullptr);
225225
static void EmitNon32BitOvfCheck(IR::Instr *instr, IR::Instr *insertInstr, IR::LabelInstr* bailOutLabel);
226+
IR::BranchInstr* InsertMissingItemCompareBranch(IR::Opnd* compareSrc, IR::Opnd* missingItemOpnd, Js::OpCode opcode, IR::LabelInstr* target, IR::Instr* insertBeforeInstr);
226227

227228
static void LowerInt4NegWithBailOut(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel);
228229
static void LowerInt4AddWithBailOut(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel);

lib/Backend/Opnd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ class Opnd
226226
bool IsUnsigned() const { return IRType_IsUnsignedInt(this->m_type); }
227227
int GetSize() const { return TySize[this->m_type]; }
228228
bool IsInt64() const { return IRType_IsInt64(this->m_type); }
229+
bool IsUint64() const { return this->m_type == TyUint64; }
229230
bool IsInt32() const { return this->m_type == TyInt32; }
230231
bool IsUInt32() const { return this->m_type == TyUint32; }
231232
bool IsIntegral32() const { return IsInt32() || IsUInt32(); }

lib/Backend/amd64/LowererMDArch.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3448,3 +3448,22 @@ LowererMDArch::LowerEHRegionReturn(IR::Instr * insertBeforeInstr, IR::Opnd * tar
34483448
// return the last instruction inserted
34493449
return retInstr;
34503450
}
3451+
3452+
IR::BranchInstr*
3453+
LowererMDArch::InsertMissingItemCompareBranch(IR::Opnd* compareSrc, IR::Opnd* missingItemOpnd, Js::OpCode opcode, IR::LabelInstr* target, IR::Instr* insertBeforeInstr)
3454+
{
3455+
Assert(compareSrc->IsFloat64() && missingItemOpnd->IsUint64());
3456+
3457+
IR::Opnd * compareSrcUint64Opnd = IR::RegOpnd::New(TyUint64, m_func);
3458+
3459+
if (compareSrc->IsRegOpnd())
3460+
{
3461+
this->lowererMD->EmitReinterpretPrimitive(compareSrcUint64Opnd, compareSrc, insertBeforeInstr);
3462+
}
3463+
else if (compareSrc->IsIndirOpnd())
3464+
{
3465+
compareSrcUint64Opnd = compareSrc->UseWithNewType(TyUint64, m_func);
3466+
}
3467+
3468+
return this->lowererMD->m_lowerer->InsertCompareBranch(missingItemOpnd, compareSrcUint64Opnd, opcode, target, insertBeforeInstr);
3469+
}

lib/Backend/amd64/LowererMDArch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class LowererMDArch
151151

152152
void LowerInlineSpreadArgOutLoop(IR::Instr *callInstr, IR::RegOpnd *indexOpnd, IR::RegOpnd *arrayElementsStartOpnd);
153153
IR::Instr * LowerEHRegionReturn(IR::Instr * insertBeforeInstr, IR::Opnd * targetOpnd);
154-
154+
IR::BranchInstr* InsertMissingItemCompareBranch(IR::Opnd* compareSrc, IR::Opnd* missingItemOpnd, Js::OpCode opcode, IR::LabelInstr* target, IR::Instr* insertBeforeInstr);
155155
private:
156156
void MovArgFromReg2Stack(IR::Instr * instr, RegNum reg, Js::ArgSlot slotNumber, IRType type = TyMachReg);
157157
void GenerateStackAllocation(IR::Instr *instr, uint32 size);

lib/Backend/arm/ARMEncode.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,20 @@ static const FormTable Forms_VMOVARMVFP[] =
12031203
FT (NOMORE, 0x0, 0),
12041204
};
12051205

1206+
static const FormTable Forms_VMOVF64R32L[] =
1207+
{
1208+
FT(2dr______, 0x0b10ee00, Steps_FLT_FMSR_d0r),
1209+
FT(2rd______, 0x0b10ee10, Steps_FLT_FMRS_rd0),
1210+
FT(NOMORE, 0x0, 0),
1211+
};
1212+
1213+
static const FormTable Forms_VMOVF64R32U[] =
1214+
{
1215+
FT(2dr______, 0x0b10ee20, Steps_FLT_FMSR_d1r),
1216+
FT(2rd______, 0x0b10ee30, Steps_FLT_FMRS_rd1),
1217+
FT(NOMORE, 0x0, 0),
1218+
};
1219+
12061220
static const FormTable Forms_VCVTF64F32 [] =
12071221
{
12081222
FT (2dd______, 0x0ac0eeb7, Steps_FCVTDS_ds),

lib/Backend/arm/AssemblyStep.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,13 +789,41 @@ static const AssemblyStep Steps_FLT_FMSR_sr [] =
789789
STEP_OPCODE, STEP_DONE
790790
};
791791

792+
static const AssemblyStep Steps_FLT_FMSR_d0r[] =
793+
{
794+
STEP_DREG, 0, 23, STEP_NEXTOPN,
795+
STEP_REG, 28,
796+
STEP_OPCODE, STEP_DONE
797+
};
798+
799+
static const AssemblyStep Steps_FLT_FMSR_d1r[] =
800+
{
801+
STEP_DREG, 0, 23, STEP_NEXTOPN,
802+
STEP_REG, 28,
803+
STEP_OPCODE, STEP_DONE
804+
};
805+
792806
static const AssemblyStep Steps_FLT_FMRS_rs [] =
793807
{
794808
STEP_REG, 28, STEP_NEXTOPN,
795809
STEP_SREG, 0, 23,
796810
STEP_OPCODE, STEP_DONE
797811
};
798812

813+
static const AssemblyStep Steps_FLT_FMRS_rd0[] =
814+
{
815+
STEP_REG, 28, STEP_NEXTOPN,
816+
STEP_DREG, 0, 23,
817+
STEP_OPCODE, STEP_DONE
818+
};
819+
820+
static const AssemblyStep Steps_FLT_FMRS_rd1[] =
821+
{
822+
STEP_REG, 28, STEP_NEXTOPN,
823+
STEP_DREG, 0, 23,
824+
STEP_OPCODE, STEP_DONE
825+
};
826+
799827
static const AssemblyStep Steps_T2_PLD_offset [] =
800828
{
801829
STEP_BASED, STEP_BASEREG, 0,

0 commit comments

Comments
 (0)