Skip to content

Commit 9587507

Browse files
pleathrajatd
authored andcommitted
[CVE-2017-266] Protect store-element to a float typed array from implicit call if BailOutOnArrayAccessHelperCall is set, as that bailout kind indicates that downstream code will assume no side-effects.
1 parent f022afb commit 9587507

18 files changed

Lines changed: 202 additions & 21 deletions

lib/Backend/Func.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ Func::Codegen(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
322322
workItem->GetJITFunctionBody()->GetProfileInfo()->DisableSwitchOpt();
323323
outputData->disableSwitchOpt = TRUE;
324324
}
325+
else if (ex.Reason() == RejitReason::ArrayCheckHoistDisabled || ex.Reason() == RejitReason::ArrayAccessHelperCallEliminationDisabled)
326+
{
327+
workItem->GetJITFunctionBody()->GetProfileInfo()->DisableArrayCheckHoist(func.IsLoopBody());
328+
outputData->disableArrayCheckHoist = TRUE;
329+
}
325330
else
326331
{
327332
Assert(ex.Reason() == RejitReason::TrackIntOverflowDisabled);

lib/Backend/GlobOpt.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20053,6 +20053,12 @@ GlobOpt::DoArrayLengthHoist() const
2005320053
return doArrayLengthHoist;
2005420054
}
2005520055

20056+
bool
20057+
GlobOpt::DoEliminateArrayAccessHelperCall(Func *const func)
20058+
{
20059+
return DoArrayCheckHoist(func);
20060+
}
20061+
2005620062
bool
2005720063
GlobOpt::DoEliminateArrayAccessHelperCall() const
2005820064
{

lib/Backend/GlobOpt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,7 @@ class GlobOpt
16161616
static bool DoArrayMissingValueCheckHoist(Func *const func);
16171617
static bool DoArraySegmentHoist(const ValueType baseValueType, Func *const func);
16181618
static bool DoArrayLengthHoist(Func *const func);
1619+
static bool DoEliminateArrayAccessHelperCall(Func* func);
16191620
static bool DoTypedArrayTypeSpec(Func* func);
16201621
static bool DoNativeArrayTypeSpec(Func* func);
16211622
static bool IsSwitchOptEnabled(Func* func);

lib/Backend/JITTimeProfileInfo.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ JITTimeProfileInfo::DisableAggressiveIntTypeSpec(bool isLoopBody)
143143
m_profileData.flags |= isLoopBody ? Flags_disableAggressiveIntTypeSpec_jitLoopBody : Flags_disableAggressiveIntTypeSpec;
144144
}
145145

146+
void
147+
JITTimeProfileInfo::DisableArrayCheckHoist(bool isLoopBody)
148+
{
149+
m_profileData.flags |= isLoopBody ? Flags_disableArrayCheckHoist_jitLoopBody : Flags_disableArrayCheckHoist;
150+
}
151+
146152
void
147153
JITTimeProfileInfo::DisableStackArgOpt()
148154
{

lib/Backend/JITTimeProfileInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class JITTimeProfileInfo
4040
void DisableStackArgOpt();
4141
void DisableSwitchOpt();
4242
void DisableTrackCompoundedIntOverflow();
43+
void DisableArrayCheckHoist(bool isLoopBody);
4344

4445
bool IsModulusOpByPowerOf2(Js::ProfileId profileId) const;
4546
bool IsAggressiveIntTypeSpecDisabled(const bool isJitLoopBody) const;

lib/Backend/Lower.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16874,16 +16874,18 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef)
1687416874
const IR::AutoReuseOpnd autoReuseReg(reg, m_func);
1687516875
InsertMove(reg, src, stElem);
1687616876

16877+
bool bailOutOnHelperCall = stElem->HasBailOutInfo() && (stElem->GetBailOutKind() & IR::BailOutOnArrayAccessHelperCall);
16878+
1687716879
// Convert to float, and assign to indirOpnd
1687816880
if (baseValueType.IsLikelyOptimizedVirtualTypedArray())
1687916881
{
1688016882
IR::RegOpnd* dstReg = IR::RegOpnd::New(indirOpnd->GetType(), this->m_func);
16881-
m_lowererMD.EmitLoadFloat(dstReg, reg, stElem);
16883+
m_lowererMD.EmitLoadFloat(dstReg, reg, stElem, bailOutOnHelperCall);
1688216884
InsertMove(indirOpnd, dstReg, stElem);
1688316885
}
1688416886
else
1688516887
{
16886-
m_lowererMD.EmitLoadFloat(indirOpnd, reg, stElem);
16888+
m_lowererMD.EmitLoadFloat(indirOpnd, reg, stElem, bailOutOnHelperCall);
1688716889
}
1688816890

1688916891
}

lib/Backend/LowerMDShared.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6645,7 +6645,7 @@ LowererMD::EmitLoadFloatCommon(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertIn
66456645
}
66466646

66476647
IR::RegOpnd *
6648-
LowererMD::EmitLoadFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr)
6648+
LowererMD::EmitLoadFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr, bool bailOutOnHelperCall)
66496649
{
66506650
IR::LabelInstr *labelDone;
66516651
IR::Instr *instr;
@@ -6657,6 +6657,23 @@ LowererMD::EmitLoadFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr)
66576657
return nullptr;
66586658
}
66596659

6660+
if (bailOutOnHelperCall)
6661+
{
6662+
if(!GlobOpt::DoEliminateArrayAccessHelperCall(this->m_func))
6663+
{
6664+
// Array access helper call removal is already off for some reason. Prevent trying to rejit again
6665+
// because it won't help and the same thing will happen again. Just abort jitting this function.
6666+
if(PHASE_TRACE(Js::BailOutPhase, this->m_func))
6667+
{
6668+
Output::Print(_u(" Aborting JIT because EliminateArrayAccessHelperCall is already off\n"));
6669+
Output::Flush();
6670+
}
6671+
throw Js::OperationAbortedException();
6672+
}
6673+
6674+
throw Js::RejitException(RejitReason::ArrayAccessHelperCallEliminationDisabled);
6675+
}
6676+
66606677
IR::Opnd *memAddress = dst;
66616678

66626679
if (dst->IsRegOpnd())

lib/Backend/LowerMDShared.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ class LowererMD
222222
static IR::Instr *InsertConvertFloat64ToInt32(const RoundMode roundMode, IR::Opnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr);
223223
void ConvertFloatToInt32(IR::Opnd* intOpnd, IR::Opnd* floatOpnd, IR::LabelInstr * labelHelper, IR::LabelInstr * labelDone, IR::Instr * instInsert);
224224
void EmitLoadFloatFromNumber(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr);
225-
IR::RegOpnd * EmitLoadFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr);
225+
IR::RegOpnd * EmitLoadFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr, bool bailOutOnHelperCall = false);
226226
static void EmitNon32BitOvfCheck(IR::Instr *instr, IR::Instr *insertInstr, IR::LabelInstr* bailOutLabel);
227227

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

lib/Backend/NativeCodeGenerator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,10 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
11351135

11361136
if (body->HasDynamicProfileInfo())
11371137
{
1138+
if (jitWriteData.disableArrayCheckHoist)
1139+
{
1140+
body->GetAnyDynamicProfileInfo()->DisableArrayCheckHoist(workItem->Type() == JsLoopBodyWorkItemType);
1141+
}
11381142
if (jitWriteData.disableAggressiveIntTypeSpec)
11391143
{
11401144
body->GetAnyDynamicProfileInfo()->DisableAggressiveIntTypeSpec(workItem->Type() == JsLoopBodyWorkItemType);

lib/Backend/amd64/LowererMDArch.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,19 +2748,19 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo
27482748
// Known to be non-integer. If we are required to bail out on helper call, just re-jit.
27492749
if (!doFloatToIntFastPath && bailOutOnHelper)
27502750
{
2751-
if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func))
2751+
if(!GlobOpt::DoEliminateArrayAccessHelperCall(this->m_func))
27522752
{
2753-
// Aggressive int type specialization is already off for some reason. Prevent trying to rejit again
2753+
// Array access helper call removal is already off for some reason. Prevent trying to rejit again
27542754
// because it won't help and the same thing will happen again. Just abort jitting this function.
27552755
if(PHASE_TRACE(Js::BailOutPhase, this->m_func))
27562756
{
2757-
Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n"));
2757+
Output::Print(_u(" Aborting JIT because EliminateArrayAccessHelperCall is already off\n"));
27582758
Output::Flush();
27592759
}
27602760
throw Js::OperationAbortedException();
27612761
}
27622762

2763-
throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled);
2763+
throw Js::RejitException(RejitReason::ArrayAccessHelperCallEliminationDisabled);
27642764
}
27652765
}
27662766
else

0 commit comments

Comments
 (0)