Skip to content

Commit ff21352

Browse files
pleathMikeHolman
authored andcommitted
[CVE-2017-0071] Handle conversion of src operand on store to a typed array if the bailout kind tells us to bail out on helper calls.
1 parent c30253b commit ff21352

12 files changed

Lines changed: 135 additions & 18 deletions

File tree

lib/Backend/Lower.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17076,7 +17076,8 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef)
1707617076

1707717077
// Convert reg to int32
1707817078
// Note: ToUint32 is implemented as (uint32)ToInt32()
17079-
m_lowererMD.EmitLoadInt32(instr, true /*conversionFromObjectAllowed*/);
17079+
bool bailOutOnHelperCall = (stElem->HasBailOutInfo() && (stElem->GetBailOutKind() & IR::BailOutOnArrayAccessHelperCall));
17080+
m_lowererMD.EmitLoadInt32(instr, true /*conversionFromObjectAllowed*/, bailOutOnHelperCall, labelHelper);
1708017081

1708117082
// MOV indirOpnd, reg
1708217083
InsertMove(indirOpnd, reg, stElem);

lib/Backend/LowerMDShared.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7932,9 +7932,9 @@ LowererMD::EmitLoadVar(IR::Instr *instrLoad, bool isFromUint32, bool isHelper)
79327932
}
79337933

79347934
bool
7935-
LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed)
7935+
LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut)
79367936
{
7937-
return lowererMDArch.EmitLoadInt32(instrLoad, conversionFromObjectAllowed);
7937+
return lowererMDArch.EmitLoadInt32(instrLoad, conversionFromObjectAllowed, bailOutOnHelper, labelBailOut);
79387938
}
79397939

79407940
void

lib/Backend/LowerMDShared.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class LowererMD
210210
static void EmitPtrInstr(IR::Instr *instr);
211211
void EmitLoadVar(IR::Instr *instr, bool isFromUint32 = false, bool isHelper = false);
212212
void EmitLoadVarNoCheck(IR::RegOpnd * dst, IR::RegOpnd * src, IR::Instr *instrLoad, bool isFromUint32, bool isHelper);
213-
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed);
213+
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr);
214214
void EmitIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
215215
void EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
216216
void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);

lib/Backend/amd64/LowererMDArch.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,7 +2605,7 @@ LowererMDArch::EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrIns
26052605
}
26062606

26072607
bool
2608-
LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed)
2608+
LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut)
26092609
{
26102610
//
26112611
// r1 = MOV src1
@@ -2658,8 +2658,29 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo
26582658
(src1ValueType.IsLikelyFloat() || src1ValueType.IsLikelyUntaggedInt()) &&
26592659
!(instrLoad->HasBailOutInfo() && (instrLoad->GetBailOutKind() == IR::BailOutIntOnly || instrLoad->GetBailOutKind() == IR::BailOutExpectingInteger));
26602660

2661-
if (!isNotInt)
2661+
if (isNotInt)
26622662
{
2663+
// Known to be non-integer. If we are required to bail out on helper call, just re-jit.
2664+
if (!doFloatToIntFastPath && bailOutOnHelper)
2665+
{
2666+
if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func))
2667+
{
2668+
// Aggressive int type specialization is already off for some reason. Prevent trying to rejit again
2669+
// because it won't help and the same thing will happen again. Just abort jitting this function.
2670+
if(PHASE_TRACE(Js::BailOutPhase, this->m_func))
2671+
{
2672+
Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n"));
2673+
Output::Flush();
2674+
}
2675+
throw Js::OperationAbortedException();
2676+
}
2677+
2678+
throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled);
2679+
}
2680+
}
2681+
else
2682+
{
2683+
// It could be an integer in this case.
26632684
if (!isInt)
26642685
{
26652686
if(doFloatToIntFastPath)
@@ -2747,7 +2768,13 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo
27472768
return true;
27482769
}
27492770

2750-
if (conversionFromObjectAllowed)
2771+
if (bailOutOnHelper)
2772+
{
2773+
Assert(labelBailOut);
2774+
lowererMD->m_lowerer->InsertBranch(Js::OpCode::Br, labelBailOut, instrLoad);
2775+
instrLoad->Remove();
2776+
}
2777+
else if (conversionFromObjectAllowed)
27512778
{
27522779
lowererMD->m_lowerer->LowerUnaryHelperMem(instrLoad, IR::HelperConv_ToInt32);
27532780
}

lib/Backend/amd64/LowererMDArch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class LowererMDArch
9797
void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
9898
void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
9999
void EmitLongToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
100-
bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed);
100+
bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOnHelperCall, IR::LabelInstr * labelBailOut);
101101

102102
IR::Instr * LoadCheckedFloat(IR::RegOpnd *opndOrig, IR::RegOpnd *opndFloat, IR::LabelInstr *labelInline, IR::LabelInstr *labelHelper, IR::Instr *instrInsert, const bool checkForNullInLoopBody = false);
103103

lib/Backend/arm/LowerMD.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7336,7 +7336,7 @@ LowererMD::EmitLoadVarNoCheck(IR::RegOpnd * dst, IR::RegOpnd * src, IR::Instr *i
73367336
}
73377337

73387338
bool
7339-
LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed)
7339+
LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut)
73407340
{
73417341
// isInt:
73427342
// dst = ASR r1, AtomTag
@@ -7380,8 +7380,29 @@ LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed)
73807380
(src1ValueType.IsLikelyFloat() || src1ValueType.IsLikelyUntaggedInt()) &&
73817381
!(instrLoad->HasBailOutInfo() && (instrLoad->GetBailOutKind() == IR::BailOutIntOnly || instrLoad->GetBailOutKind() == IR::BailOutExpectingInteger));
73827382

7383-
if (!isNotInt)
7383+
if (isNotInt)
73847384
{
7385+
// Known to be non-integer. If we are required to bail out on helper call, just re-jit.
7386+
if (!doFloatToIntFastPath && bailOutOnHelper)
7387+
{
7388+
if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func))
7389+
{
7390+
// Aggressive int type specialization is already off for some reason. Prevent trying to rejit again
7391+
// because it won't help and the same thing will happen again. Just abort jitting this function.
7392+
if(PHASE_TRACE(Js::BailOutPhase, this->m_func))
7393+
{
7394+
Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n"));
7395+
Output::Flush();
7396+
}
7397+
throw Js::OperationAbortedException();
7398+
}
7399+
7400+
throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled);
7401+
}
7402+
}
7403+
else
7404+
{
7405+
// Could be an integer in this case.
73857406
if (!isInt)
73867407
{
73877408
if(doFloatToIntFastPath)
@@ -7438,7 +7459,13 @@ LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed)
74387459
return true;
74397460
}
74407461

7441-
if (conversionFromObjectAllowed)
7462+
if (bailOutOnHelper)
7463+
{
7464+
Assert(labelBailOut);
7465+
this->m_lowerer->InsertBranch(Js::OpCode::Br, labelBailOut, instrLoad);
7466+
instrLoad->Remove();
7467+
}
7468+
else if (conversionFromObjectAllowed)
74427469
{
74437470
this->m_lowerer->LowerUnaryHelperMem(instrLoad, IR::HelperConv_ToInt32);
74447471
}

lib/Backend/arm/LowerMD.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class LowererMD
143143
static void EmitInt4Instr(IR::Instr *instr);
144144
static void EmitPtrInstr(IR::Instr *instr);
145145
void EmitLoadVar(IR::Instr *instr, bool isFromUint32 = false, bool isHelper = false);
146-
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed);
146+
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr);
147147
IR::Instr * LowerInt64Assign(IR::Instr * instr) { Assert(UNREACHED); return nullptr; }
148148

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

lib/Backend/arm64/LowerMD.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class LowererMD
140140
static void EmitInt4Instr(IR::Instr *instr) { __debugbreak(); }
141141
static void EmitPtrInstr(IR::Instr *instr) { __debugbreak(); }
142142
void EmitLoadVar(IR::Instr *instr, bool isFromUint32 = false, bool isHelper = false) { __debugbreak(); }
143-
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed) { __debugbreak(); return 0; }
143+
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr) { __debugbreak(); return 0; }
144144
IR::Instr * LowerInt64Assign(IR::Instr * instr) { __debugbreak(); return nullptr; }
145145

146146
static void LowerInt4NegWithBailOut(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel) { __debugbreak(); }

lib/Backend/i386/LowererMDArch.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,7 +2605,7 @@ LowererMDArch::EmitLongToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInser
26052605
}
26062606

26072607
bool
2608-
LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed)
2608+
LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut)
26092609
{
26102610
// if(doShiftFirst)
26112611
// {
@@ -2663,9 +2663,29 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo
26632663
instrLoad->InsertBefore(instr);
26642664
}
26652665

2666-
// It could be an integer in this case
2667-
if (!isNotInt)
2666+
if (isNotInt)
26682667
{
2668+
// Known to be non-integer. If we are required to bail out on helper call, just re-jit.
2669+
if (!doFloatToIntFastPath && bailOutOnHelper)
2670+
{
2671+
if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func))
2672+
{
2673+
// Aggressive int type specialization is already off for some reason. Prevent trying to rejit again
2674+
// because it won't help and the same thing will happen again. Just abort jitting this function.
2675+
if(PHASE_TRACE(Js::BailOutPhase, this->m_func))
2676+
{
2677+
Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n"));
2678+
Output::Flush();
2679+
}
2680+
throw Js::OperationAbortedException();
2681+
}
2682+
2683+
throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled);
2684+
}
2685+
}
2686+
else
2687+
{
2688+
// It could be an integer in this case
26692689
if(doShiftFirst)
26702690
{
26712691
// r1 = SAR r1, VarTag_Shift (move last-shifted bit into CF)
@@ -2781,7 +2801,13 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo
27812801
return true;
27822802
}
27832803

2784-
if (conversionFromObjectAllowed)
2804+
if (bailOutOnHelper)
2805+
{
2806+
Assert(labelBailOut);
2807+
lowererMD->m_lowerer->InsertBranch(Js::OpCode::Br, labelBailOut, instrLoad);
2808+
instrLoad->Remove();
2809+
}
2810+
else if (conversionFromObjectAllowed)
27852811
{
27862812
lowererMD->m_lowerer->LowerUnaryHelperMem(instrLoad, IR::HelperConv_ToInt32);
27872813
}

lib/Backend/i386/LowererMDArch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class LowererMDArch
8585
void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
8686
void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
8787
void EmitLongToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
88-
bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed);
88+
bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr);
8989

9090
IR::Instr * LoadCheckedFloat(IR::RegOpnd *opndOrig, IR::RegOpnd *opndFloat, IR::LabelInstr *labelInline, IR::LabelInstr *labelHelper, IR::Instr *instrInsert, const bool checkForNullInLoopBody = false);
9191

0 commit comments

Comments
 (0)