Skip to content

Commit c1bdfff

Browse files
MikeHolmanleirocks
authored andcommitted
[CVE-2017-11838] [ChakraCore] - JIT optimization vulnerability could lead to RCE - Individual
1 parent 5a4e655 commit c1bdfff

2 files changed

Lines changed: 42 additions & 44 deletions

File tree

lib/Backend/IRBuilder.cpp

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ IRBuilder::CreateLabel(IR::BranchInstr * branchInstr, uint& offset)
10941094
instrPrev = targetInstr->GetPrevRealInstrOrLabel();
10951095
}
10961096

1097-
if (instrPrev && instrPrev->IsLabelInstr())
1097+
if (instrPrev && instrPrev->IsLabelInstr() && instrPrev->GetByteCodeOffset() == offset)
10981098
{
10991099
// Found an existing label at the right offset. Just reuse it.
11001100
labelInstr = instrPrev->AsLabelInstr();
@@ -1103,7 +1103,7 @@ IRBuilder::CreateLabel(IR::BranchInstr * branchInstr, uint& offset)
11031103
{
11041104
// No label at the desired offset. Create one.
11051105

1106-
labelInstr = IR::LabelInstr::New( Js::OpCode::Label, this->m_func);
1106+
labelInstr = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
11071107
labelInstr->SetByteCodeOffset(offset);
11081108
if (instrPrev)
11091109
{
@@ -2690,35 +2690,52 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
26902690

26912691
case Js::OpCode::ProfiledLoopBodyStart:
26922692
{
2693-
if (!(m_func->DoSimpleJitDynamicProfile() && m_func->GetJITFunctionBody()->DoJITLoopBody()))
2693+
// This opcode is removed from the IR when we aren't doing Profiling SimpleJit or not jitting loop bodies
2694+
if (m_func->DoSimpleJitDynamicProfile() && m_func->GetJITFunctionBody()->DoJITLoopBody())
26942695
{
2695-
// This opcode is removed from the IR when we aren't doing Profiling SimpleJit or not jitting loop bodies
2696-
break;
2697-
}
2696+
// Attach a register to the dest of this instruction to communicate whether we should bail out (the deciding of this is done in lowering)
2697+
IR::Opnd* fullJitExists = IR::RegOpnd::New(TyUint8, m_func);
2698+
auto start = m_lastInstr;
2699+
2700+
if (start->m_opcode == Js::OpCode::InitLoopBodyCount)
2701+
{
2702+
Assert(this->IsLoopBody());
2703+
start = start->m_prev;
2704+
}
2705+
2706+
Assert(start->m_opcode == Js::OpCode::ProfiledLoopStart && start->GetDst());
2707+
IR::JitProfilingInstr* instr = IR::JitProfilingInstr::New(Js::OpCode::ProfiledLoopBodyStart, fullJitExists, start->GetDst(), m_func);
2708+
// profileId is used here to represent the loop number
2709+
instr->loopNumber = num;
2710+
this->AddInstr(instr, offset);
26982711

2699-
// Attach a register to the dest of this instruction to communicate whether we should bail out (the deciding of this is done in lowering)
2700-
IR::Opnd* fullJitExists = IR::RegOpnd::New(TyUint8, m_func);
2701-
auto start = m_lastInstr->m_prev;
2712+
// If fullJitExists isn't 0, bail out so that we can get the fulljitted version
2713+
BailOutInfo * bailOutInfo = JitAnew(m_func->m_alloc, BailOutInfo, instr->GetByteCodeOffset(), m_func);
2714+
IR::BailOutInstr * bailInstr = IR::BailOutInstr::New(Js::OpCode::BailOnNotEqual, IR::BailOnSimpleJitToFullJitLoopBody, bailOutInfo, bailOutInfo->bailOutFunc);
2715+
bailInstr->SetSrc1(fullJitExists);
2716+
bailInstr->SetSrc2(IR::IntConstOpnd::New(0, TyUint8, m_func, true));
2717+
this->AddInstr(bailInstr, offset);
27022718

2703-
if (start->m_opcode == Js::OpCode::InitLoopBodyCount)
2704-
{
2705-
Assert(this->IsLoopBody());
2706-
start = start->m_prev;
27072719
}
27082720

2709-
Assert(start->m_opcode == Js::OpCode::ProfiledLoopStart && start->GetDst());
2710-
IR::JitProfilingInstr* instr = IR::JitProfilingInstr::New(Js::OpCode::ProfiledLoopBodyStart, fullJitExists, start->GetDst(), m_func);
2711-
// profileId is used here to represent the loop number
2712-
instr->loopNumber = num;
2713-
this->AddInstr(instr, offset);
2721+
Js::ImplicitCallFlags flags = Js::ImplicitCall_HasNoInfo;
2722+
Js::LoopFlags loopFlags;
2723+
if (this->m_func->HasProfileInfo())
2724+
{
2725+
flags = m_func->GetReadOnlyProfileInfo()->GetLoopImplicitCallFlags(num);
2726+
loopFlags = m_func->GetReadOnlyProfileInfo()->GetLoopFlags(num);
2727+
}
27142728

2715-
// If fullJitExists isn't 0, bail out so that we can get the fulljitted version
2716-
BailOutInfo * bailOutInfo = JitAnew(m_func->m_alloc, BailOutInfo, instr->GetByteCodeOffset(), m_func);
2717-
IR::BailOutInstr * bailInstr = IR::BailOutInstr::New(Js::OpCode::BailOnNotEqual, IR::BailOnSimpleJitToFullJitLoopBody, bailOutInfo, bailOutInfo->bailOutFunc);
2718-
bailInstr->SetSrc1(fullJitExists);
2719-
bailInstr->SetSrc2(IR::IntConstOpnd::New(0, TyUint8, m_func, true));
2720-
this->AddInstr(bailInstr, offset);
2729+
// Put a label the instruction stream to carry the profile info
2730+
IR::ProfiledLabelInstr * labelInstr = IR::ProfiledLabelInstr::New(Js::OpCode::Label, this->m_func, flags, loopFlags);
2731+
#if DBG
2732+
labelInstr->loopNum = num;
2733+
#endif
2734+
m_lastInstr->InsertAfter(labelInstr);
2735+
m_lastInstr = labelInstr;
27212736

2737+
// Set it to the offset to the start of the loop
2738+
labelInstr->SetByteCodeOffset(m_jnReader.GetCurrentOffset());
27222739
break;
27232740
}
27242741

@@ -2750,29 +2767,10 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
27502767
this->AddInstr(instr, offset);
27512768
}
27522769

2753-
Js::ImplicitCallFlags flags = Js::ImplicitCall_HasNoInfo;
2754-
Js::LoopFlags loopFlags;
2755-
if (this->m_func->HasProfileInfo())
2756-
{
2757-
flags = m_func->GetReadOnlyProfileInfo()->GetLoopImplicitCallFlags(num);
2758-
loopFlags = m_func->GetReadOnlyProfileInfo()->GetLoopFlags(num);
2759-
}
2760-
27612770
if (this->IsLoopBody() && !m_loopCounterSym)
27622771
{
27632772
InsertInitLoopBodyLoopCounter(num);
27642773
}
2765-
2766-
// Put a label the instruction stream to carry the profile info
2767-
IR::ProfiledLabelInstr * labelInstr = IR::ProfiledLabelInstr::New(Js::OpCode::Label, this->m_func, flags, loopFlags);
2768-
#if DBG
2769-
labelInstr->loopNum = num;
2770-
#endif
2771-
m_lastInstr->InsertAfter(labelInstr);
2772-
m_lastInstr = labelInstr;
2773-
2774-
// Set it to the offset to the start of the loop
2775-
labelInstr->SetByteCodeOffset(m_jnReader.GetCurrentOffset());
27762774
break;
27772775
}
27782776

lib/Backend/IRBuilderAsmJs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ IRBuilderAsmJs::CreateLabel(IR::BranchInstr * branchInstr, uint & offset)
995995
}
996996

997997
IR::LabelInstr * labelInstr;
998-
if (instrPrev && instrPrev->IsLabelInstr())
998+
if (instrPrev && instrPrev->IsLabelInstr() && instrPrev->GetByteCodeOffset() == offset)
999999
{
10001000
// Found an existing label at the right offset. Just reuse it.
10011001
labelInstr = instrPrev->AsLabelInstr();

0 commit comments

Comments
 (0)