Skip to content

Commit 42485b9

Browse files
committed
[MERGE #6375 @akroshg] ChakraCore servicing fixes for Feb release
Merge pull request #6375 from akroshg:servicing/2002 Fixes following CVEs [CVE-2020-0710] [CVE-2020-0711] [CVE-2020-0712] [CVE-2020-0713] [CVE-2020-0767]
2 parents 9741bdf + 23eca47 commit 42485b9

18 files changed

+513
-72
lines changed

Build/NuGet/.pack-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.11.15
1+
1.11.16

lib/Backend/JnHelperMethodList.h

+11
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ HELPERCALLCHK(Op_PatchPutValueWithThisPtrNoLocalFastPathPolymorphic, ((void (*)(
254254
HELPERCALLCHK(Op_PatchPutRootValueNoLocalFastPath, ((void (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutRootValueNoLocalFastPath<true, Js::InlineCache>), AttrCanThrow)
255255
HELPERCALLCHK(Op_PatchPutRootValueNoLocalFastPathPolymorphic, ((void (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutRootValueNoLocalFastPath<true, Js::PolymorphicInlineCache>), AttrCanThrow)
256256

257+
HELPERCALLCHK(Op_PatchInitValueCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::RecyclableObject*, Js::PropertyId, Js::Var))Js::JavascriptOperators::PatchInitValueCheckLayout<Js::InlineCache>), AttrCanThrow)
258+
HELPERCALLCHK(Op_PatchInitValuePolymorphicCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::RecyclableObject*, Js::PropertyId, Js::Var))Js::JavascriptOperators::PatchInitValueCheckLayout<Js::PolymorphicInlineCache>), AttrCanThrow)
259+
HELPERCALLCHK(Op_PatchPutValueCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueCheckLayout<Js::InlineCache>), AttrCanThrow)
260+
HELPERCALLCHK(Op_PatchPutValueWithThisPtrCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrCheckLayout<Js::InlineCache>), AttrCanThrow)
261+
HELPERCALLCHK(Op_PatchPutValuePolymorphicCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueCheckLayout<Js::PolymorphicInlineCache>), AttrCanThrow)
262+
HELPERCALLCHK(Op_PatchPutValueWithThisPtrPolymorphicCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrCheckLayout<Js::PolymorphicInlineCache>), AttrCanThrow)
263+
HELPERCALLCHK(Op_PatchPutValueNoLocalFastPathCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueNoLocalFastPathCheckLayout<Js::InlineCache>), AttrCanThrow)
264+
HELPERCALLCHK(Op_PatchPutValueWithThisPtrNoLocalFastPathCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCheckLayout<Js::InlineCache>), AttrCanThrow)
265+
HELPERCALLCHK(Op_PatchPutValueNoLocalFastPathPolymorphicCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueNoLocalFastPathCheckLayout<Js::PolymorphicInlineCache>), AttrCanThrow)
266+
HELPERCALLCHK(Op_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCheckLayout<Js::PolymorphicInlineCache>), AttrCanThrow)
267+
257268
HELPERCALLCHK(Op_PatchSetPropertyScoped, ((void (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::FrameDisplay*, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchSetPropertyScoped<true, Js::InlineCache>), AttrCanThrow)
258269
HELPERCALLCHK(Op_ConsolePatchSetPropertyScoped, ((void(*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::FrameDisplay*, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchSetPropertyScoped<true, Js::InlineCache>), AttrCanThrow)
259270

lib/Backend/Lower.cpp

+88-17
Original file line numberDiff line numberDiff line change
@@ -7107,6 +7107,57 @@ Lowerer::LowerStFld(
71077107
IR::Opnd *dst = stFldInstr->UnlinkDst();
71087108
AssertMsg(dst->IsSymOpnd() && dst->AsSymOpnd()->m_sym->IsPropertySym(), "Expected property sym as dst of field store");
71097109

7110+
BailOutInfo * bailOutInfo = nullptr;
7111+
bool doCheckLayout = false;
7112+
IR::PropertySymOpnd * propertySymOpnd = nullptr;
7113+
if (dst->AsSymOpnd()->IsPropertySymOpnd())
7114+
{
7115+
propertySymOpnd = dst->AsPropertySymOpnd();
7116+
if (stFldInstr->HasBailOutInfo() && !propertySymOpnd->IsTypeCheckSeqCandidate() && propertySymOpnd->TypeCheckRequired())
7117+
{
7118+
IR::Instr * instrBailTarget = stFldInstr->ShareBailOut();
7119+
LowerBailTarget(instrBailTarget);
7120+
doCheckLayout = true;
7121+
bailOutInfo = stFldInstr->GetBailOutInfo();
7122+
switch (helperMethod)
7123+
{
7124+
case IR::HelperOp_PatchPutValue:
7125+
helperMethod = IR::HelperOp_PatchPutValueCheckLayout;
7126+
break;
7127+
case IR::HelperOp_PatchPutValuePolymorphic:
7128+
helperMethod = IR::HelperOp_PatchPutValuePolymorphicCheckLayout;
7129+
break;
7130+
case IR::HelperOp_PatchPutValueNoLocalFastPath:
7131+
helperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathCheckLayout;
7132+
break;
7133+
case IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphic:
7134+
helperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphicCheckLayout;
7135+
break;
7136+
case IR::HelperOp_PatchPutValueWithThisPtr:
7137+
helperMethod = IR::HelperOp_PatchPutValueWithThisPtrCheckLayout;
7138+
break;
7139+
case IR::HelperOp_PatchPutValueWithThisPtrPolymorphic:
7140+
helperMethod = IR::HelperOp_PatchPutValueWithThisPtrPolymorphicCheckLayout;
7141+
break;
7142+
case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPath:
7143+
helperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathCheckLayout;
7144+
break;
7145+
case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphic:
7146+
helperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCheckLayout;
7147+
break;
7148+
case IR::HelperOp_PatchInitValue:
7149+
helperMethod = IR::HelperOp_PatchInitValueCheckLayout;
7150+
break;
7151+
case IR::HelperOp_PatchInitValuePolymorphic:
7152+
helperMethod = IR::HelperOp_PatchInitValuePolymorphicCheckLayout;
7153+
break;
7154+
default:
7155+
AssertOrFailFast(false);
7156+
break;
7157+
}
7158+
}
7159+
}
7160+
71107161
IR::Opnd * inlineCacheOpnd = nullptr;
71117162
if (withInlineCache)
71127163
{
@@ -7153,7 +7204,20 @@ Lowerer::LowerStFld(
71537204
}
71547205

71557206
IR::RegOpnd *opndBase = dst->AsSymOpnd()->CreatePropertyOwnerOpnd(m_func);
7156-
m_lowererMD.ChangeToHelperCall(stFldInstr, helperMethod, labelBailOut, opndBase, dst->AsSymOpnd()->IsPropertySymOpnd() ? dst->AsSymOpnd()->AsPropertySymOpnd() : nullptr, isHelper);
7207+
7208+
IR::Instr * callInstr =
7209+
m_lowererMD.ChangeToHelperCall(stFldInstr, helperMethod, labelBailOut, opndBase, propertySymOpnd, isHelper);
7210+
7211+
if (doCheckLayout)
7212+
{
7213+
callInstr->SetDst(IR::RegOpnd::New(TyUint8, bailOutInfo->bailOutFunc));
7214+
IR::Instr * bailOutInstr = IR::BailOutInstr::New(Js::OpCode::BailOnNotEqual, IR::BailOutFailedTypeCheck, bailOutInfo, bailOutInfo->bailOutFunc);
7215+
bailOutInstr->SetSrc1(callInstr->GetDst());
7216+
bailOutInstr->SetSrc2(IR::IntConstOpnd::New(0, TyUint8, bailOutInfo->bailOutFunc));
7217+
callInstr->InsertAfter(bailOutInstr);
7218+
bailOutInfo->polymorphicCacheIndex = propertySymOpnd->m_inlineCacheIndex;
7219+
LowerBailOnEqualOrNotEqual(bailOutInstr, nullptr, nullptr, nullptr, isHelper);
7220+
}
71577221

71587222
return instrPrev;
71597223
}
@@ -24950,9 +25014,9 @@ Lowerer::GenerateLdHomeObj(IR::Instr* instr)
2495025014
Func *func = instr->m_func;
2495125015

2495225016
IR::LabelInstr *labelDone = IR::LabelInstr::New(Js::OpCode::Label, func, false);
24953-
IR::LabelInstr *labelInlineFunc = IR::LabelInstr::New(Js::OpCode::Label, func, false);
2495425017
IR::LabelInstr *testLabel = IR::LabelInstr::New(Js::OpCode::Label, func, false);
2495525018
IR::LabelInstr *scriptFuncLabel = IR::LabelInstr::New(Js::OpCode::Label, func, false);
25019+
LABELNAMESET(scriptFuncLabel, "ScriptFunctionWithHomeObj");
2495625020
IR::Opnd *opndUndefAddress = this->LoadLibraryValueOpnd(instr, LibraryValue::ValueUndefined);
2495725021

2495825022
IR::RegOpnd *instanceRegOpnd = IR::RegOpnd::New(TyMachPtr, func);
@@ -24973,23 +25037,30 @@ Lowerer::GenerateLdHomeObj(IR::Instr* instr)
2497325037

2497425038
if (func->GetJITFunctionBody()->HasHomeObj())
2497525039
{
24976-
// Is this an function with inline cache and home obj??
24977-
IR::Opnd * vtableAddressInlineFuncHomObjOpnd = this->LoadVTableValueOpnd(instr, VTableValue::VtableScriptFunctionWithInlineCacheAndHomeObj);
24978-
IR::BranchInstr* inlineFuncHomObjOpndBr = InsertCompareBranch(IR::IndirOpnd::New(instanceRegOpnd, 0, TyMachPtr, func), vtableAddressInlineFuncHomObjOpnd, Js::OpCode::BrNeq_A, labelInlineFunc, instr);
24979-
InsertObjectPoison(instanceRegOpnd, inlineFuncHomObjOpndBr, instr, false);
24980-
IR::IndirOpnd *indirInlineFuncHomeObjOpnd = IR::IndirOpnd::New(instanceRegOpnd, Js::FunctionWithHomeObj<Js::ScriptFunctionWithInlineCache>::GetOffsetOfHomeObj(), TyMachPtr, func);
24981-
Lowerer::InsertMove(instanceRegOpnd, indirInlineFuncHomeObjOpnd, instr);
24982-
InsertBranch(Js::OpCode::Br, testLabel, instr);
25040+
IR::RegOpnd* funcObjHasInlineCachesOpnd = IR::RegOpnd::New(TyUint8, instr->m_func);
25041+
this->InsertMove(funcObjHasInlineCachesOpnd, IR::IndirOpnd::New(instanceRegOpnd, Js::ScriptFunction::GetOffsetOfHasInlineCaches(), TyUint8, instr->m_func), instr);
2498325042

24984-
instr->InsertBefore(labelInlineFunc);
24985-
24986-
// Is this a function with inline cache, home obj and computed name??
24987-
IR::Opnd * vtableAddressInlineFuncHomObjCompNameOpnd = this->LoadVTableValueOpnd(instr, VTableValue::VtableScriptFunctionWithInlineCacheHomeObjAndComputedName);
24988-
IR::BranchInstr* inlineFuncHomObjCompNameBr = InsertCompareBranch(IR::IndirOpnd::New(instanceRegOpnd, 0, TyMachPtr, func), vtableAddressInlineFuncHomObjCompNameOpnd, Js::OpCode::BrNeq_A, scriptFuncLabel, instr);
25043+
IR::BranchInstr* inlineFuncHomObjCompNameBr = InsertTestBranch(funcObjHasInlineCachesOpnd, funcObjHasInlineCachesOpnd, Js::OpCode::BrEq_A, scriptFuncLabel, instr);
2498925044
InsertObjectPoison(instanceRegOpnd, inlineFuncHomObjCompNameBr, instr, false);
24990-
IR::IndirOpnd *indirInlineFuncHomeObjCompNameOpnd = IR::IndirOpnd::New(instanceRegOpnd, Js::FunctionWithComputedName<Js::FunctionWithHomeObj<Js::ScriptFunctionWithInlineCache>>::GetOffsetOfHomeObj(), TyMachPtr, func);
24991-
Lowerer::InsertMove(instanceRegOpnd, indirInlineFuncHomeObjCompNameOpnd, instr);
24992-
InsertBranch(Js::OpCode::Br, testLabel, instr);
25045+
25046+
if (func->GetJITFunctionBody()->HasComputedName())
25047+
{
25048+
// Is this a function with inline cache, home obj and computed name?
25049+
{
25050+
IR::IndirOpnd* indirInlineFuncHomeObjCompNameOpnd = IR::IndirOpnd::New(instanceRegOpnd, Js::FunctionWithComputedName<Js::FunctionWithHomeObj<Js::ScriptFunctionWithInlineCache>>::GetOffsetOfHomeObj(), TyMachPtr, func);
25051+
Lowerer::InsertMove(instanceRegOpnd, indirInlineFuncHomeObjCompNameOpnd, instr);
25052+
InsertBranch(Js::OpCode::Br, testLabel, instr);
25053+
}
25054+
}
25055+
else
25056+
{
25057+
// Is this a function with inline cache and home obj?
25058+
{
25059+
IR::IndirOpnd* indirInlineFuncHomeObjOpnd = IR::IndirOpnd::New(instanceRegOpnd, Js::FunctionWithHomeObj<Js::ScriptFunctionWithInlineCache>::GetOffsetOfHomeObj(), TyMachPtr, func);
25060+
Lowerer::InsertMove(instanceRegOpnd, indirInlineFuncHomeObjOpnd, instr);
25061+
InsertBranch(Js::OpCode::Br, testLabel, instr);
25062+
}
25063+
}
2499325064

2499425065
instr->InsertBefore(scriptFuncLabel);
2499525066
IR::IndirOpnd *indirOpnd = IR::IndirOpnd::New(instanceRegOpnd, Js::ScriptFunctionWithHomeObj::GetOffsetOfHomeObj(), TyMachPtr, func);

lib/Common/ChakraCoreVersion.h

+1-1
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 15
20+
#define CHAKRA_CORE_PATCH_VERSION 16
2121
#define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0.
2222

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

lib/Parser/Parse.cpp

+22-4
Original file line numberDiff line numberDiff line change
@@ -1738,6 +1738,20 @@ void Parser::BindPidRefsInScope(IdentPtr pid, Symbol *sym, int blockId, uint max
17381738
}
17391739
}
17401740

1741+
if (m_currentNodeFunc && m_currentNodeFunc->pnodeName && pid == m_currentNodeFunc->pnodeName->pid && !m_currentNodeFunc->IsDeclaration() && m_currentNodeFunc->IsBodyAndParamScopeMerged())
1742+
{
1743+
Scope* funcExprScope = m_currentNodeFunc->scope;
1744+
Assert(funcExprScope->GetScopeType() == ScopeType_FuncExpr);
1745+
1746+
ParseNodeBlock* bodyScope = m_currentNodeFunc->pnodeBodyScope;
1747+
Assert(bodyScope->blockType == PnodeBlockType::Function);
1748+
1749+
if (ref->GetScopeId() < bodyScope->blockId && ref->GetScopeId() > blockId)
1750+
{
1751+
funcExprScope->SetIsObject();
1752+
}
1753+
}
1754+
17411755
if (ref->GetScopeId() == blockId)
17421756
{
17431757
break;
@@ -4938,6 +4952,12 @@ ParseNodeFnc * Parser::ParseFncDeclInternal(ushort flags, LPCOLESTR pNameHint, c
49384952
pnodeFnc->SetIsBaseClassConstructor((flags & fFncBaseClassConstructor) != 0);
49394953
pnodeFnc->SetHomeObjLocation(Js::Constants::NoRegister);
49404954

4955+
if (this->m_currentScope && this->m_currentScope->GetScopeType() == ScopeType_Parameter)
4956+
{
4957+
pnodeFnc->SetIsDeclaredInParamScope();
4958+
this->m_currentScope->SetHasNestedParamFunc();
4959+
}
4960+
49414961
IdentPtr pFncNamePid = nullptr;
49424962
bool needScanRCurly = true;
49434963
ParseFncDeclHelper<buildAST>(pnodeFnc, pNameHint, flags, fUnaryOrParen, noStmtContext, &needScanRCurly, fModule, &pFncNamePid, fAllowIn);
@@ -8378,17 +8398,15 @@ ParseNodePtr Parser::ParseExpr(int oplMin,
83788398
// binding operator, be it unary or binary.
83798399
Error(ERRsyntax);
83808400
}
8381-
if (m_currentScope->GetScopeType() == ScopeType_Parameter
8382-
|| (m_currentScope->GetScopeType() == ScopeType_Block && m_currentScope->GetEnclosingScope()->GetScopeType() == ScopeType_Parameter)) // Check whether this is a class definition inside param scope
8401+
if(m_currentScope->AncestorScopeIsParameter()) // Yield is not allowed within any parameter scope
83838402
{
83848403
Error(ERRsyntax);
83858404
}
83868405
}
83878406
else if (nop == knopAwait)
83888407
{
83898408
if (!this->GetScanner()->AwaitIsKeywordRegion() ||
8390-
m_currentScope->GetScopeType() == ScopeType_Parameter ||
8391-
(m_currentScope->GetScopeType() == ScopeType_Block && m_currentScope->GetEnclosingScope()->GetScopeType() == ScopeType_Parameter)) // Check whether this is a class definition inside param scope
8409+
m_currentScope->AncestorScopeIsParameter()) // Await is not allowed within any parameter scope
83928410
{
83938411
// As with the 'yield' keyword, the case where 'await' is scanned as a keyword (tkAWAIT)
83948412
// but the scanner is not treating await as a keyword (!this->GetScanner()->AwaitIsKeyword())

lib/Parser/ptree.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ enum FncFlags : uint
445445
kFunctionIsStaticMember = 1 << 24,
446446
kFunctionIsGenerator = 1 << 25, // Function is an ES6 generator function
447447
kFunctionAsmjsMode = 1 << 26,
448-
// Free = 1 << 27,
448+
kFunctionIsDeclaredInParamScope = 1 << 27, // Function is declared in parameter scope (ex: inside default argument)
449449
kFunctionIsAsync = 1 << 28, // function is async
450450
kFunctionHasDirectSuper = 1 << 29, // super()
451451
kFunctionIsDefaultModuleExport = 1 << 30, // function is the default export of a module
@@ -583,6 +583,7 @@ class ParseNodeFnc : public ParseNode
583583
void SetHasHomeObj(bool set = true) { SetFlags(kFunctionHasHomeObj, set); }
584584
void SetUsesArguments(bool set = true) { SetFlags(kFunctionUsesArguments, set); }
585585
void SetIsDefaultModuleExport(bool set = true) { SetFlags(kFunctionIsDefaultModuleExport, set); }
586+
void SetIsDeclaredInParamScope(bool set = true) { SetFlags(kFunctionIsDeclaredInParamScope, set); }
586587
void SetNestedFuncEscapes(bool set = true) { nestedFuncEscapes = set; }
587588
void SetCanBeDeferred(bool set = true) { canBeDeferred = set; }
588589
void ResetBodyAndParamScopeMerged() { isBodyAndParamScopeMerged = false; }
@@ -623,6 +624,7 @@ class ParseNodeFnc : public ParseNode
623624
bool HasHomeObj() const { return HasFlags(kFunctionHasHomeObj); }
624625
bool UsesArguments() const { return HasFlags(kFunctionUsesArguments); }
625626
bool IsDefaultModuleExport() const { return HasFlags(kFunctionIsDefaultModuleExport); }
627+
bool IsDeclaredInParamScope() const { return HasFlags(kFunctionIsDeclaredInParamScope); }
626628
bool NestedFuncEscapes() const { return nestedFuncEscapes; }
627629
bool CanBeDeferred() const { return canBeDeferred; }
628630
bool IsBodyAndParamScopeMerged() { return isBodyAndParamScopeMerged; }

0 commit comments

Comments
 (0)