Skip to content

Commit 63c5099

Browse files
committed
[MERGE #6500 @boingoing] ChakraCore Servicing update for 2020.09B
Merge pull request #6500 from boingoing:servicing/2009 [CVE-2020-0878] [CVE-2020-1180] [CVE-2020-1057] [CVE-2020-1172]
2 parents b12499b + 337129e commit 63c5099

File tree

17 files changed

+259
-52
lines changed

17 files changed

+259
-52
lines changed

Build/NuGet/.pack-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.11.21
1+
1.11.22

lib/Backend/BackwardPass.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8648,20 +8648,7 @@ BackwardPass::SetWriteThroughSymbolsSetForRegion(BasicBlock * catchOrFinallyBloc
86488648
bool
86498649
BackwardPass::CheckWriteThroughSymInRegion(Region* region, StackSym* sym)
86508650
{
8651-
if (region->GetType() == RegionTypeRoot)
8652-
{
8653-
return false;
8654-
}
8655-
8656-
// if the current region is a try region, check in its write-through set,
8657-
// otherwise (current = catch region) look in the first try ancestor's write-through set
8658-
Region * selfOrFirstTryAncestor = region->GetSelfOrFirstTryAncestor();
8659-
if (!selfOrFirstTryAncestor)
8660-
{
8661-
return false;
8662-
}
8663-
Assert(selfOrFirstTryAncestor->GetType() == RegionTypeTry);
8664-
return selfOrFirstTryAncestor->writeThroughSymbolsSet && selfOrFirstTryAncestor->writeThroughSymbolsSet->Test(sym->m_id);
8651+
return region->CheckWriteThroughSym(sym);
86658652
}
86668653

86678654
#if DBG

lib/Backend/Func.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
5555
m_localClosureSym(nullptr),
5656
m_paramClosureSym(nullptr),
5757
m_localFrameDisplaySym(nullptr),
58+
m_inlineeFrameDisplaySyms(nullptr),
5859
m_bailoutReturnValueSym(nullptr),
5960
m_hasBailedOutSym(nullptr),
6061
m_inlineeFrameStartSym(nullptr),
@@ -1124,6 +1125,16 @@ void Func::InitLocalClosureSyms()
11241125
}
11251126
}
11261127

1128+
void
1129+
Func::AddInlineeFrameDisplaySym(StackSym *inlineeFrameDisplaySym)
1130+
{
1131+
if (m_inlineeFrameDisplaySyms == nullptr)
1132+
{
1133+
m_inlineeFrameDisplaySyms = JitAnew(this->m_alloc, SList<StackSym*>, this->m_alloc);
1134+
}
1135+
m_inlineeFrameDisplaySyms->Prepend(inlineeFrameDisplaySym);
1136+
}
1137+
11271138
bool
11281139
Func::IsTrackCompoundedIntOverflowDisabled() const
11291140
{

lib/Backend/Func.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
441441

442442
StackSym *GetLocalFrameDisplaySym() const { return m_localFrameDisplaySym; }
443443
void SetLocalFrameDisplaySym(StackSym *sym) { m_localFrameDisplaySym = sym; }
444+
void AddInlineeFrameDisplaySym(StackSym *sym);
444445

445446
intptr_t GetJittedLoopIterationsSinceLastBailoutAddress() const;
446447
void EnsurePinnedTypeRefs();
@@ -678,6 +679,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
678679
StackSym * m_paramClosureSym;
679680
StackSym * m_localFrameDisplaySym;
680681
StackSym * m_bailoutReturnValueSym;
682+
SList<StackSym*> * m_inlineeFrameDisplaySyms;
681683
StackSym * m_hasBailedOutSym;
682684
uint m_forInLoopMaxDepth;
683685
uint m_forInLoopBaseDepth;

lib/Backend/GlobOpt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,8 @@ class GlobOpt
960960
void KillAllObjectTypes(BVSparse<JitArenaAllocator>* liveFields = nullptr);
961961
void EndFieldLifetime(IR::SymOpnd *symOpnd);
962962
PropertySym * CopyPropPropertySymObj(IR::SymOpnd *opnd, IR::Instr *instr);
963+
void OnCopyPropInPrePass(StackSym * copySym, IR::Instr * instr, BasicBlock * block);
964+
void UpdateUpwardExposedUses(StackSym * sym, IR::Instr * instrLast, BasicBlock * block, JsUtil::Stack<BasicBlock*, JitArenaAllocator, true> *blockStack, BVSparse<JitArenaAllocator>* blocksProcessed);
963965
static bool NeedsTypeCheckBailOut(const IR::Instr *instr, IR::PropertySymOpnd *propertySymOpnd, bool isStore, bool* pIsTypeCheckProtected, IR::BailOutKind *pBailOutKind);
964966
IR::Instr * PreOptPeep(IR::Instr *instr);
965967
IR::Instr * OptPeep(IR::Instr *instr, Value *src1Val, Value *src2Val);

lib/Backend/GlobOptFields.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,11 @@ GlobOpt::CopyPropPropertySymObj(IR::SymOpnd *symOpnd, IR::Instr *instr)
19171917
symOpnd->m_sym = newProp;
19181918
symOpnd->SetIsJITOptimizedReg(true);
19191919

1920+
if (this->IsLoopPrePass())
1921+
{
1922+
this->OnCopyPropInPrePass(copySym, instr, this->currentBlock);
1923+
}
1924+
19201925
if (symOpnd->IsPropertySymOpnd())
19211926
{
19221927
IR::PropertySymOpnd *propertySymOpnd = symOpnd->AsPropertySymOpnd();
@@ -1959,6 +1964,77 @@ GlobOpt::CopyPropPropertySymObj(IR::SymOpnd *symOpnd, IR::Instr *instr)
19591964
return propertySym;
19601965
}
19611966

1967+
void
1968+
GlobOpt::OnCopyPropInPrePass(StackSym * copySym, IR::Instr * instr, BasicBlock * block)
1969+
{
1970+
// Copy prop in the prepass may make upwardExposedUses out of date. Update it now.
1971+
1972+
if (block->upwardExposedUses->Test(copySym->m_id))
1973+
{
1974+
// Nothing to do
1975+
return;
1976+
}
1977+
1978+
// Use a to-do stack to avoid recursion and a bv to avoid repeated work
1979+
JsUtil::Stack<BasicBlock*, JitArenaAllocator, true> blockStack(this->tempAlloc);
1980+
BVSparse<JitArenaAllocator> blocksProcessed(this->tempAlloc);
1981+
1982+
blocksProcessed.Set(block->GetBlockNum());
1983+
this->UpdateUpwardExposedUses(copySym, instr, block, &blockStack, &blocksProcessed);
1984+
1985+
while (!blockStack.Empty())
1986+
{
1987+
block = blockStack.Pop();
1988+
Assert(blocksProcessed.Test(block->GetBlockNum()));
1989+
this->UpdateUpwardExposedUses(copySym, block->GetLastInstr(), block, &blockStack, &blocksProcessed);
1990+
}
1991+
}
1992+
1993+
void
1994+
GlobOpt::UpdateUpwardExposedUses(StackSym * sym, IR::Instr * instrLast, BasicBlock * block, JsUtil::Stack<BasicBlock*, JitArenaAllocator, true> *blockStack, BVSparse<JitArenaAllocator>* blocksProcessed)
1995+
{
1996+
Assert(blocksProcessed->Test(block->GetBlockNum()));
1997+
Assert(!block->upwardExposedUses->Test(sym->m_id));
1998+
1999+
// Walk the block backward looking for a def. If the sym is write-through in this block, though,
2000+
// treat it as upward-exposed regardless of the presence of defs.
2001+
IR::LabelInstr * instrFirst = block->GetFirstInstr()->AsLabelInstr();
2002+
Region * region = instrFirst->GetRegion();
2003+
if (region == nullptr || !region->CheckWriteThroughSym(sym))
2004+
{
2005+
FOREACH_INSTR_BACKWARD_IN_RANGE(instr, instrLast, instrFirst)
2006+
{
2007+
// If the instr defines the sym, quit without setting upwardExposedUses
2008+
IR::Opnd * dst = instr->GetDst();
2009+
if (dst != nullptr && dst->GetStackSym() == sym)
2010+
{
2011+
return;
2012+
}
2013+
Assert(dst == nullptr || dst->GetStackSym() == nullptr || dst->GetStackSym()->m_id != sym->m_id);
2014+
}
2015+
NEXT_INSTR_BACKWARD_IN_RANGE;
2016+
}
2017+
2018+
// The sym is upward exposed at this block. Now update the to-do set with the predecessors.
2019+
2020+
Assert(block->GetBlockNum() != 0);
2021+
block->upwardExposedUses->Set(sym->m_id);
2022+
FOREACH_PREDECESSOR_BLOCK(blockPred, block)
2023+
{
2024+
if (blockPred->upwardExposedUses == nullptr || blockPred->upwardExposedUses->Test(sym->m_id))
2025+
{
2026+
// If the bv is null, that means the main pass is done with this block
2027+
// and so done with its predecessors
2028+
continue;
2029+
}
2030+
if (!blocksProcessed->TestAndSet(blockPred->GetBlockNum()))
2031+
{
2032+
blockStack->Push(blockPred);
2033+
}
2034+
}
2035+
NEXT_PREDECESSOR_BLOCK;
2036+
}
2037+
19622038
void
19632039
GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
19642040
{

lib/Backend/IRBuilder.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,11 @@ IRBuilder::Build()
661661
dstOpnd, m_func),
662662
offset);
663663
}
664+
else if (m_func->GetTopFunc()->DoStackFrameDisplay())
665+
{
666+
Assert(m_func->GetLocalFrameDisplaySym() != nullptr);
667+
m_func->GetTopFunc()->AddInlineeFrameDisplaySym(m_func->GetLocalFrameDisplaySym());
668+
}
664669
}
665670
}
666671
}

lib/Backend/Lower.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,11 @@ Lowerer::Lower()
4949
{
5050
EnsureStackFunctionListStackSym();
5151
}
52+
StackSym * symInlineeFrameDisplayEnd = nullptr;
5253
if (m_func->DoStackFrameDisplay() && !m_func->IsLoopBody())
5354
{
54-
AllocStackClosure();
55+
symInlineeFrameDisplayEnd = StackSym::New(m_func);
56+
AllocStackClosure(symInlineeFrameDisplayEnd);
5557
}
5658

5759
AllocStackForInObjectEnumeratorArray();
@@ -140,6 +142,11 @@ Lowerer::Lower()
140142
EnsureZeroLastStackFunctionNext();
141143
}
142144

145+
if (symInlineeFrameDisplayEnd != nullptr)
146+
{
147+
InitializeInlineeFrameDisplays(symInlineeFrameDisplayEnd);
148+
}
149+
143150
if (!m_func->IsSimpleJit())
144151
{
145152
#if 0 // TODO michhol oop jit, reenable assert
@@ -6755,10 +6762,40 @@ Lowerer::EnsureStackFunctionListStackSym()
67556762
}
67566763

67576764
void
6758-
Lowerer::AllocStackClosure()
6765+
Lowerer::AllocStackClosure(StackSym * symInlineeFrameDisplayEnd)
67596766
{
67606767
m_func->StackAllocate(m_func->GetLocalFrameDisplaySym(), sizeof(Js::Var));
67616768
m_func->StackAllocate(m_func->GetLocalClosureSym(), sizeof(Js::Var));
6769+
6770+
if (m_func->m_inlineeFrameDisplaySyms != nullptr)
6771+
{
6772+
FOREACH_SLIST_ENTRY(StackSym*, sym, m_func->m_inlineeFrameDisplaySyms)
6773+
{
6774+
m_func->StackAllocate(sym, sizeof(Js::Var));
6775+
}
6776+
NEXT_SLIST_ENTRY;
6777+
}
6778+
m_func->StackAllocate(symInlineeFrameDisplayEnd, sizeof(Js::Var));
6779+
}
6780+
6781+
void
6782+
Lowerer::InitializeInlineeFrameDisplays(StackSym * symInlineeFrameDisplayEnd)
6783+
{
6784+
if (m_func->m_inlineeFrameDisplaySyms != nullptr)
6785+
{
6786+
FOREACH_SLIST_ENTRY(StackSym*, sym, m_func->m_inlineeFrameDisplaySyms)
6787+
{
6788+
Assert(sym->IsAllocated());
6789+
InsertMove(IR::SymOpnd::New(sym, TyMachReg, m_func),
6790+
IR::AddrOpnd::New(m_func->GetThreadContextInfo()->GetNullFrameDisplayAddr(), IR::AddrOpndKindDynamicMisc, m_func),
6791+
m_func->GetFunctionEntryInsertionPoint());
6792+
}
6793+
NEXT_SLIST_ENTRY;
6794+
}
6795+
Assert(symInlineeFrameDisplayEnd->IsAllocated());
6796+
InsertMove(IR::SymOpnd::New(symInlineeFrameDisplayEnd, TyMachReg, m_func),
6797+
IR::AddrOpnd::New((void*)0, IR::AddrOpndKindDynamicMisc, m_func),
6798+
m_func->GetFunctionEntryInsertionPoint());
67626799
}
67636800

67646801
void
@@ -27112,6 +27149,12 @@ void Lowerer::LowerLdFrameDisplay(IR::Instr *instr, bool doStackFrameDisplay)
2711227149
else
2711327150
{
2711427151
GenerateRecyclerAlloc(IR::HelperAllocMemForFrameDisplay, allocSize, dstOpnd, instr);
27152+
if (instr->m_func != this->m_func && this->m_func->DoStackFrameDisplay())
27153+
{
27154+
StackSym * inlineeFrameDisplaySym = instr->m_func->GetLocalFrameDisplaySym();
27155+
Assert(inlineeFrameDisplaySym->IsAllocated());
27156+
InsertMove(IR::SymOpnd::New(inlineeFrameDisplaySym, TyMachReg, m_func), dstOpnd, instr);
27157+
}
2711527158
}
2711627159

2711727160
// Copy contents of environment

lib/Backend/Lower.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ class Lowerer
196196

197197
void EnsureStackFunctionListStackSym();
198198
void EnsureZeroLastStackFunctionNext();
199-
void AllocStackClosure();
199+
void AllocStackClosure(StackSym * symInlineeFrameDisplayEnd);
200+
void InitializeInlineeFrameDisplays(StackSym * symInlineeFrameDisplayEnd);
200201
IR::Instr * GenerateNewStackScFunc(IR::Instr * newScFuncInstr, IR::RegOpnd ** ppEnvOpnd);
201202
void GenerateStackScriptFunctionInit(StackSym * stackSym, Js::FunctionInfoPtrPtr nestedInfo);
202203
void GenerateScriptFunctionInit(IR::RegOpnd * regOpnd, IR::Opnd * vtableAddressOpnd,

lib/Backend/Region.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,21 @@ Region::GetFirstAncestorOfNonExceptingFinally()
103103
return ancestor;
104104
}
105105

106+
bool
107+
Region::CheckWriteThroughSym(StackSym * sym)
108+
{
109+
if (this->GetType() == RegionTypeRoot)
110+
{
111+
return false;
112+
}
113+
114+
// if the current region is a try region, check in its write-through set,
115+
// otherwise (current = catch region) look in the first try ancestor's write-through set
116+
Region * selfOrFirstTryAncestor = this->GetSelfOrFirstTryAncestor();
117+
if (!selfOrFirstTryAncestor)
118+
{
119+
return false;
120+
}
121+
Assert(selfOrFirstTryAncestor->GetType() == RegionTypeTry);
122+
return selfOrFirstTryAncestor->writeThroughSymbolsSet && selfOrFirstTryAncestor->writeThroughSymbolsSet->Test(sym->m_id);
123+
}

lib/Backend/Region.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class Region
6868
Region * GetSelfOrFirstTryAncestor();
6969
Region * GetFirstAncestorOfNonExceptingFinallyParent();
7070
Region * GetFirstAncestorOfNonExceptingFinally();
71+
bool CheckWriteThroughSym(StackSym * sym);
7172

7273
private:
7374
RegionType type;

lib/Common/ChakraCoreVersion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// ChakraCore version number definitions (used in ChakraCore binary metadata)
1818
#define CHAKRA_CORE_MAJOR_VERSION 1
1919
#define CHAKRA_CORE_MINOR_VERSION 11
20-
#define CHAKRA_CORE_PATCH_VERSION 21
20+
#define CHAKRA_CORE_PATCH_VERSION 22
2121
#define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0.
2222

2323
// -------------

lib/Parser/Scan.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,24 @@ class UTF8EncodingPolicyBase
241241
OLECHAR ReadRest(OLECHAR ch, EncodedCharPtr &p, EncodedCharPtr last)
242242
{
243243
EncodedCharPtr s;
244+
utf8::DecodeOptions decodeOptions = m_decodeOptions;
244245
if (bScan)
245246
{
246247
s = p;
247248
}
248249
OLECHAR result = utf8::DecodeTail(ch, p, last, m_decodeOptions);
249250
if (bScan)
250251
{
251-
// If we are scanning, update m_cMultiUnits counter.
252-
m_cMultiUnits += p - s;
252+
if ((decodeOptions & utf8::doSecondSurrogatePair) && (p - s > 2))
253+
{
254+
// 4 byte utf8 chars equals 2 utf16 chars + 2 multi-unit chars only (refer to case4: in utf8::DecodeTail()).
255+
m_cMultiUnits += 2;
256+
}
257+
else
258+
{
259+
// If we are scanning, update m_cMultiUnits counter.
260+
m_cMultiUnits += p - s;
261+
}
253262
}
254263
return result;
255264
}

lib/Runtime/Base/Constants.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,12 @@ namespace Js
132132
static const int StackNestedFuncList = 2;
133133
static const int StackFrameDisplay = 3;
134134
static const int StackScopeSlots = 4;
135+
static const int InlineeFrameDisplays = 5;
135136
#if _M_IX86 || _M_AMD64
136137
static const int StackNestedFuncListWithNoArg = 1;
137138
static const int StackFrameDisplayWithNoArg = 2;
138139
static const int StackScopeSlotsWithNoArg = 3;
140+
static const int InlineeFrameDisplaysWithNoArg = 4;
139141
#endif
140142

141143
static const DWORD NonWebWorkerContextId = 0;

lib/Runtime/Language/JavascriptFunctionArgIndex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ namespace Js
1313
JavascriptFunctionArgIndex_StackNestedFuncListWithNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::StackNestedFuncListWithNoArg,
1414
JavascriptFunctionArgIndex_StackFrameDisplayNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::StackFrameDisplayWithNoArg,
1515
JavascriptFunctionArgIndex_StackScopeSlotsNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::StackScopeSlotsWithNoArg,
16+
JavascriptFunctionArgIndex_InlineeFrameDisplaysNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::InlineeFrameDisplaysWithNoArg,
1617
#endif
1718
JavascriptFunctionArgIndex_StackNestedFuncList = JavascriptFunctionArgIndex_Frame - Js::Constants::StackNestedFuncList,
1819
JavascriptFunctionArgIndex_StackFrameDisplay = JavascriptFunctionArgIndex_Frame - Js::Constants::StackFrameDisplay,
1920
JavascriptFunctionArgIndex_StackScopeSlots = JavascriptFunctionArgIndex_Frame - Js::Constants::StackScopeSlots,
21+
JavascriptFunctionArgIndex_InlineeFrameDisplays = JavascriptFunctionArgIndex_Frame - Js::Constants::InlineeFrameDisplays,
2022
JavascriptFunctionArgIndex_Function = 0,
2123
JavascriptFunctionArgIndex_CallInfo = 1,
2224
JavascriptFunctionArgIndex_This = 2, /* (hidden) first script arg */

0 commit comments

Comments
 (0)