Skip to content

Commit fdf0aeb

Browse files
committed
[MERGE #6385 @pleath] ChakraCore Servicing Update for 2020.03B
Merge pull request #6385 from pleath:servicing/2003 Changes to address the following issues: CVE-2020-0768 CVE-2020-0811 CVE-2020-0812 CVE-2020-0813 CVE-2020-0823 CVE-2020-0825 CVE-2020-0826 CVE-2020-0827 CVE-2020-0828 CVE-2020-0829 CVE-2020-0830 CVE-2020-0831 CVE-2020-0848
2 parents 42485b9 + 48f74e6 commit fdf0aeb

27 files changed

+29116
-29059
lines changed

lib/Backend/BackwardPass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5891,7 +5891,7 @@ BackwardPass::InsertTypeTransitionsAtPotentialKills()
58915891
// This is the sym we're tracking. No aliasing to worry about.
58925892
return false;
58935893
}
5894-
if (propertySymOpnd->IsMono() && data->GetInitialType() != propertySymOpnd->GetType())
5894+
if (propertySymOpnd->NeedsMonoCheck() && data->GetInitialType() != propertySymOpnd->GetType())
58955895
{
58965896
// Type mismatch in a monomorphic case -- no aliasing.
58975897
return false;

lib/Backend/GlobOpt.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2903,7 +2903,12 @@ GlobOpt::OptTagChecks(IR::Instr *instr)
29032903
// the byteCodeUse fields...
29042904
TrackByteCodeUsesForInstrAddedInOptInstr(bailOutInstr, [&]()
29052905
{
2906-
TryHoistInvariant(bailOutInstr, this->currentBlock, nullptr, value, nullptr, true, false, false, IR::BailOutOnTaggedValue);
2906+
if (TryHoistInvariant(bailOutInstr, this->currentBlock, nullptr, value, nullptr, true, false, false, IR::BailOutOnTaggedValue))
2907+
{
2908+
Value* landingPadValue = this->currentBlock->loop->landingPad->globOptData.FindValue(stackSym);
2909+
ValueType newLandingPadValueType = landingPadValue->GetValueInfo()->Type().SetCanBeTaggedValue(false);
2910+
ChangeValueType(nullptr, landingPadValue, newLandingPadValueType, false);
2911+
}
29072912
});
29082913
}
29092914
if (symOpnd)

lib/Backend/GlobOptArrays.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,13 @@ void GlobOpt::ArraySrcOpt::CheckLoops()
498498
if (doArrayChecks)
499499
{
500500
hoistChecksOutOfLoop = loop;
501+
502+
// If BailOnNotObject isn't hoisted, the value may still be tagged in the landing pad
503+
if (baseValueInLoopLandingPad->GetValueInfo()->Type().CanBeTaggedValue())
504+
{
505+
baseValueType = baseValueType.SetCanBeTaggedValue(true);
506+
baseOpnd->SetValueType(baseValueType);
507+
}
501508
}
502509

503510
if (isLikelyJsArray && loopKills.KillsArrayHeadSegments())
@@ -1704,9 +1711,7 @@ void GlobOpt::ArraySrcOpt::Optimize()
17041711

17051712
baseOpnd->SetValueType(baseValueType);
17061713

1707-
if (!baseValueType.IsLikelyAnyOptimizedArray() ||
1708-
!globOpt->DoArrayCheckHoist(baseValueType, globOpt->currentBlock->loop, instr) ||
1709-
(baseOwnerIndir && !globOpt->ShouldExpectConventionalArrayIndexValue(baseOwnerIndir)))
1714+
if (!baseValueType.IsLikelyAnyOptimizedArray())
17101715
{
17111716
return;
17121717
}
@@ -1721,6 +1726,16 @@ void GlobOpt::ArraySrcOpt::Optimize()
17211726
return;
17221727
}
17231728

1729+
if (!globOpt->DoArrayCheckHoist(baseValueType, globOpt->currentBlock->loop, instr) ||
1730+
(baseOwnerIndir && !globOpt->ShouldExpectConventionalArrayIndexValue(baseOwnerIndir)))
1731+
{
1732+
if (!globOpt->IsLoopPrePass() && baseValueType.IsAnyOptimizedArray())
1733+
{
1734+
globOpt->ProcessNoImplicitCallArrayUses(baseOpnd, nullptr, instr, isLikelyJsArray, isLoad || isStore || instr->m_opcode == Js::OpCode::IsIn);
1735+
}
1736+
return;
1737+
}
1738+
17241739
isLikelyVirtualTypedArray = baseValueType.IsLikelyOptimizedVirtualTypedArray();
17251740
Assert(!(isLikelyJsArray && isLikelyVirtualTypedArray));
17261741

lib/Backend/GlobOptFields.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,19 +1123,6 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd
11231123
Assert(opnd->IsTypeCheckSeqCandidate());
11241124
Assert(opnd->HasObjectTypeSym());
11251125

1126-
if (opnd->HasTypeMismatch())
1127-
{
1128-
if (emitsTypeCheckOut != nullptr)
1129-
{
1130-
*emitsTypeCheckOut = false;
1131-
}
1132-
if (changesTypeValueOut != nullptr)
1133-
{
1134-
*changesTypeValueOut = false;
1135-
}
1136-
return false;
1137-
}
1138-
11391126
bool isStore = opnd == instr->GetDst();
11401127
bool isTypeDead = opnd->IsTypeDead();
11411128
bool consumeType = makeChanges && !IsLoopPrePass();
@@ -1175,6 +1162,19 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd
11751162
opnd->SetTypeAvailable(true);
11761163
}
11771164

1165+
if (opnd->HasTypeMismatch())
1166+
{
1167+
if (emitsTypeCheckOut != nullptr)
1168+
{
1169+
*emitsTypeCheckOut = false;
1170+
}
1171+
if (changesTypeValueOut != nullptr)
1172+
{
1173+
*changesTypeValueOut = false;
1174+
}
1175+
return false;
1176+
}
1177+
11781178
bool doEquivTypeCheck = opnd->HasEquivalentTypeSet() && !opnd->NeedsMonoCheck();
11791179
if (!doEquivTypeCheck)
11801180
{

lib/Backend/IRBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,6 +1906,10 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
19061906
this->AddInstr(instr, offset);
19071907
return;
19081908
}
1909+
case Js::OpCode::InitConst:
1910+
// Don't use InitConst in the JIT, as some dataflow tracking is missing, and we don't currently optimize for it.
1911+
newOpcode = Js::OpCode::Ld_A;
1912+
break;
19091913
}
19101914

19111915
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(R0);

lib/Backend/LinearScan.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2933,9 +2933,9 @@ LinearScan::ProcessEHRegionBoundary(IR::Instr * instr)
29332933
}
29342934

29352935
// Spill everything upon entry to the try region and upon a Leave.
2936-
IR::Instr* insertionInstr = instr->m_opcode != Js::OpCode::Leave ? instr : instr->m_prev;
29372936
FOREACH_SLIST_ENTRY_EDITING(Lifetime *, lifetime, this->activeLiveranges, iter)
29382937
{
2938+
IR::Instr* insertionInstr = instr->m_opcode != Js::OpCode::Leave ? instr : instr->m_prev;
29392939
this->activeRegs.Clear(lifetime->reg);
29402940
if (lifetime->IsInt())
29412941
{

lib/Backend/Lower.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13739,6 +13739,23 @@ Lowerer::GenerateObjectTestAndTypeLoad(IR::Instr *instrLdSt, IR::RegOpnd *opndBa
1373913739
InsertMove(opndType, opndIndir, instrLdSt);
1374013740
}
1374113741

13742+
void Lowerer::InsertMoveForPolymorphicCacheIndex(IR::Instr * instr, BailOutInfo * bailOutInfo, int bailOutRecordOffset, uint polymorphicCacheIndexValue)
13743+
{
13744+
IR::Opnd * indexOpnd = nullptr;
13745+
13746+
if (this->m_func->IsOOPJIT())
13747+
{
13748+
indexOpnd = IR::IndirOpnd::New(IR::RegOpnd::New(m_func->GetTopFunc()->GetNativeCodeDataSym(), TyVar, m_func), (int)(bailOutRecordOffset + BailOutRecord::GetOffsetOfPolymorphicCacheIndex()), TyUint32, m_func);
13749+
}
13750+
else
13751+
{
13752+
indexOpnd = IR::MemRefOpnd::New((BYTE*)bailOutInfo->bailOutRecord + BailOutRecord::GetOffsetOfPolymorphicCacheIndex(), TyUint32, this->m_func);
13753+
}
13754+
13755+
InsertMove(
13756+
indexOpnd, IR::IntConstOpnd::New(polymorphicCacheIndexValue, TyUint32, this->m_func), instr, false);
13757+
}
13758+
1374213759
IR::LabelInstr *
1374313760
Lowerer::GenerateBailOut(IR::Instr * instr, IR::BranchInstr * branchInstr, IR::LabelInstr *bailOutLabel, IR::LabelInstr * collectRuntimeStatsLabel)
1374413761
{
@@ -13800,23 +13817,19 @@ Lowerer::GenerateBailOut(IR::Instr * instr, IR::BranchInstr * branchInstr, IR::L
1380013817
// Generate code to write the cache index into the bailout record before we jump to the call site.
1380113818
Assert(bailOutInfo->polymorphicCacheIndex != (uint)-1);
1380213819
Assert(bailOutInfo->bailOutRecord);
13803-
IR::Opnd * indexOpnd = nullptr;
13804-
13805-
if (this->m_func->IsOOPJIT())
13806-
{
13807-
indexOpnd = IR::IndirOpnd::New(IR::RegOpnd::New(m_func->GetTopFunc()->GetNativeCodeDataSym(), TyVar, m_func), (int)(bailOutRecordOffset + BailOutRecord::GetOffsetOfPolymorphicCacheIndex()), TyUint32, m_func);
13808-
}
13809-
else
13810-
{
13811-
indexOpnd = IR::MemRefOpnd::New((BYTE*)bailOutInfo->bailOutRecord + BailOutRecord::GetOffsetOfPolymorphicCacheIndex(), TyUint32, this->m_func);
13812-
}
13813-
13814-
InsertMove(
13815-
indexOpnd, IR::IntConstOpnd::New(bailOutInfo->polymorphicCacheIndex, TyUint32, this->m_func), instr, false);
13820+
InsertMoveForPolymorphicCacheIndex(instr, bailOutInfo, bailOutRecordOffset, bailOutInfo->polymorphicCacheIndex);
1381613821
}
1381713822

1381813823
if (bailOutInfo->bailOutRecord->IsShared())
1381913824
{
13825+
// The polymorphicCacheIndex value should be relevant only for field type check bailouts.
13826+
// In case of a shared bailout record, the polymorphicCacheIndex sticks regardless of the bailout kind being different
13827+
// from field type check. Therefore, it results in an out-of-bound write while trying to recrod a field access update.
13828+
if (instr->GetBailOutKind() != IR::BailOutFailedTypeCheck && instr->GetBailOutKind() != IR::BailOutFailedFixedFieldTypeCheck)
13829+
{
13830+
InsertMoveForPolymorphicCacheIndex(instr, bailOutInfo, bailOutRecordOffset, (uint)-1);
13831+
}
13832+
1382013833
IR::Opnd *functionBodyOpnd;
1382113834
if (this->m_func->IsOOPJIT())
1382213835
{

lib/Backend/Lower.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ class Lowerer
594594
void PreserveSourcesForBailOnResultCondition(IR::Instr *const instr, IR::LabelInstr *const skipBailOutLabel) const;
595595
void LowerInstrWithBailOnResultCondition(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel) const;
596596
void GenerateObjectTestAndTypeLoad(IR::Instr *instrLdSt, IR::RegOpnd *opndBase, IR::RegOpnd *opndType, IR::LabelInstr *labelHelper);
597+
void InsertMoveForPolymorphicCacheIndex(IR::Instr * instr, BailOutInfo * bailOutInfo, int bailOutRecordOffset, uint polymorphicCacheIndexValue);
597598
IR::LabelInstr *GenerateBailOut(IR::Instr * instr, IR::BranchInstr * branchInstr = nullptr, IR::LabelInstr * labelBailOut = nullptr, IR::LabelInstr * collectRuntimeStatsLabel = nullptr);
598599
void GenerateJumpToEpilogForBailOut(BailOutInfo * bailOutInfo, IR::Instr *instrAfter);
599600
void GenerateThrow(IR::Opnd* errorCode, IR::Instr * instr);

lib/Common/DataStructures/EvalMapString.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ namespace Js
99
template <bool fastHash>
1010
struct EvalMapStringInternal
1111
{
12+
FinalizableObject* owningVar; // This is the Var that originally owns the character buffer corresponding to this EvalMap key.
1213
JsUtil::CharacterBuffer<char16> str;
1314
hash_t hash;
1415
ModuleID moduleID;
1516
BOOL strict;
1617
BOOL isLibraryCode;
1718

18-
EvalMapStringInternal() : str(), moduleID(0), strict(FALSE), isLibraryCode(FALSE), hash(0) {};
19-
EvalMapStringInternal(__in_ecount(charLength) char16 const* content, int charLength, ModuleID moduleID, BOOL strict, BOOL isLibraryCode)
20-
: str(content, charLength), moduleID(moduleID), strict(strict), isLibraryCode(isLibraryCode)
19+
EvalMapStringInternal() : owningVar(nullptr), str(), moduleID(0), strict(FALSE), isLibraryCode(FALSE), hash(0) {};
20+
EvalMapStringInternal(FinalizableObject* obj, __in_ecount(charLength) char16 const* content, int charLength, ModuleID moduleID, BOOL strict, BOOL isLibraryCode)
21+
: owningVar(obj), str(content, charLength), moduleID(moduleID), strict(strict), isLibraryCode(isLibraryCode)
2122
{
2223
// NOTE: this hash is not equivalent to the character buffer hash
2324
// Don't use a CharacteBuffer to do a map lookup on the EvalMapString.

lib/Parser/Parse.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,9 +1744,9 @@ void Parser::BindPidRefsInScope(IdentPtr pid, Symbol *sym, int blockId, uint max
17441744
Assert(funcExprScope->GetScopeType() == ScopeType_FuncExpr);
17451745

17461746
ParseNodeBlock* bodyScope = m_currentNodeFunc->pnodeBodyScope;
1747-
Assert(bodyScope->blockType == PnodeBlockType::Function);
1747+
Assert(bodyScope == nullptr || bodyScope->blockType == PnodeBlockType::Function);
17481748

1749-
if (ref->GetScopeId() < bodyScope->blockId && ref->GetScopeId() > blockId)
1749+
if (bodyScope && ref->GetScopeId() < bodyScope->blockId && ref->GetScopeId() > blockId)
17501750
{
17511751
funcExprScope->SetIsObject();
17521752
}

0 commit comments

Comments
 (0)