Skip to content

Commit 8595cce

Browse files
committed
[1.11>master] [MERGE #6279 @MikeHolman] September 2019 Security Update
Merge pull request #6279 from MikeHolman:servicing/1909 September 2019 Security Update that addresses the following issues in ChakraCore: CVE-2019-1138 CVE-2019-1217 CVE-2019-1237 CVE-2019-1298 CVE-2019-1300
2 parents 062ef9f + 7e9a2ee commit 8595cce

14 files changed

+5021
-4660
lines changed

.gitignore

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,7 @@ build_*.log
3939
build_*.wrn
4040
Build/ipch/
4141
Build/swum-cache.txt
42-
Build/VCBuild.Lite/
43-
Build/VCBuild.NoJIT/
44-
Build/VCBuild.SWB/
45-
Build/VCBuild.ClangCL/
46-
Build/VCBuild/
42+
Build/VCBuild*/
4743
buildchk.*
4844
buildfre.*
4945
out/

lib/Backend/BackwardPass.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5636,7 +5636,14 @@ BackwardPass::TrackObjTypeSpecProperties(IR::PropertySymOpnd *opnd, BasicBlock *
56365636
// Some instr protected by this one requires a monomorphic type check. (E.g., final type opt,
56375637
// fixed field not loaded from prototype.) Note the IsTypeAvailable test above: only do this at
56385638
// the initial type check that protects this path.
5639-
opnd->SetMonoGuardType(bucket->GetMonoGuardType());
5639+
if (!opnd->SetMonoGuardType(bucket->GetMonoGuardType()))
5640+
{
5641+
// We can't safely check for the required type here. Clear the objtypespec info to disable optimization
5642+
// using this inline cache, since there appears to be a mismatch, and re-jit.
5643+
// (Dead store pass is too late to generate the bailout points we need to use this type correctly.)
5644+
this->currentInstr->m_func->ClearObjTypeSpecFldInfo(opnd->m_inlineCacheIndex);
5645+
throw Js::RejitException(RejitReason::FailedEquivalentTypeCheck);
5646+
}
56405647
this->currentInstr->ChangeEquivalentToMonoTypeCheckBailOut();
56415648
}
56425649
bucket->SetMonoGuardType(nullptr);

lib/Backend/Func.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ Func::Codegen(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
359359
case RejitReason::MemOpDisabled:
360360
outputData->disableMemOp = TRUE;
361361
break;
362+
case RejitReason::FailedEquivalentTypeCheck:
363+
// No disable flag. The thrower of the re-jit exception must guarantee that objtypespec is disabled where appropriate.
364+
break;
362365
default:
363366
Assume(UNREACHED);
364367
}
@@ -1531,6 +1534,12 @@ Func::GetObjTypeSpecFldInfo(const uint index) const
15311534
return GetWorkItem()->GetJITTimeInfo()->GetObjTypeSpecFldInfo(index);
15321535
}
15331536

1537+
void
1538+
Func::ClearObjTypeSpecFldInfo(const uint index)
1539+
{
1540+
GetWorkItem()->GetJITTimeInfo()->ClearObjTypeSpecFldInfo(index);
1541+
}
1542+
15341543
ObjTypeSpecFldInfo*
15351544
Func::GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const
15361545
{

lib/Backend/Func.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
560560
Js::Var AllocateNumber(double value);
561561

562562
ObjTypeSpecFldInfo* GetObjTypeSpecFldInfo(const uint index) const;
563+
void ClearObjTypeSpecFldInfo(const uint index);
563564
ObjTypeSpecFldInfo* GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const;
564565

565566
// Gets an inline cache pointer to use in jitted code. Cached data may not be stable while jitting. Does not return null.

lib/Backend/FunctionJITTimeInfo.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,18 @@ FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
336336
return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.objTypeSpecFldInfoArray[index]);
337337
}
338338

339+
void
340+
FunctionJITTimeInfo::ClearObjTypeSpecFldInfo(uint index)
341+
{
342+
if (m_data.objTypeSpecFldInfoArray == nullptr)
343+
{
344+
return;
345+
}
346+
AssertOrFailFast(index < m_data.objTypeSpecFldInfoCount);
347+
348+
m_data.objTypeSpecFldInfoArray[index] = nullptr;
349+
}
350+
339351
ObjTypeSpecFldInfo *
340352
FunctionJITTimeInfo::GetGlobalObjTypeSpecFldInfo(uint index) const
341353
{

lib/Backend/FunctionJITTimeInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class FunctionJITTimeInfo
4040
const BVFixed * GetInlineesBV() const;
4141
const FunctionJITTimeInfo * GetJitTimeDataFromFunctionInfoAddr(intptr_t polyFuncInfo) const;
4242
ObjTypeSpecFldInfo * GetObjTypeSpecFldInfo(uint index) const;
43+
void ClearObjTypeSpecFldInfo(uint index);
4344
ObjTypeSpecFldInfo * GetGlobalObjTypeSpecFldInfo(uint index) const;
4445
uint GetGlobalObjTypeSpecFldInfoCount() const;
4546
const FunctionJITRuntimeInfo * GetInlineeForTargetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId, intptr_t inlineeFuncBodyAddr) const;

lib/Backend/GlobOpt.cpp

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,10 @@ void GlobOpt::InsertValueCompensation(
11821182
IR::Instr *insertBeforeInstr = predecessor->GetLastInstr();
11831183
Func *const func = insertBeforeInstr->m_func;
11841184
bool setLastInstrInPredecessor;
1185+
// If this is a loop back edge, and the successor has been completed, don't attempt to update its block data.
1186+
// The update is unnecessary, and the data has likely been freed.
1187+
bool updateSuccessorBlockData = !this->isPerformingLoopBackEdgeCompensation || successor->GetDataUseCount() > 0;
1188+
11851189
if(insertBeforeInstr->IsBranchInstr() || insertBeforeInstr->m_opcode == Js::OpCode::BailTarget)
11861190
{
11871191
// Don't insert code between the branch and the corresponding ByteCodeUses instructions
@@ -1272,29 +1276,33 @@ void GlobOpt::InsertValueCompensation(
12721276
// Merge the head segment length value
12731277
Assert(predecessorBlockData.liveVarSyms->Test(predecessorHeadSegmentLengthSym->m_id));
12741278
predecessorBlockData.liveVarSyms->Set(mergedHeadSegmentLengthSym->m_id);
1275-
successorBlockData.liveVarSyms->Set(mergedHeadSegmentLengthSym->m_id);
12761279
Value *const predecessorHeadSegmentLengthValue =
12771280
predecessorBlockData.FindValue(predecessorHeadSegmentLengthSym);
12781281
Assert(predecessorHeadSegmentLengthValue);
12791282
predecessorBlockData.SetValue(predecessorHeadSegmentLengthValue, mergedHeadSegmentLengthSym);
1280-
Value *const mergedHeadSegmentLengthValue = successorBlockData.FindValue(mergedHeadSegmentLengthSym);
1281-
if(mergedHeadSegmentLengthValue)
1283+
1284+
if (updateSuccessorBlockData)
12821285
{
1283-
Assert(mergedHeadSegmentLengthValue->GetValueNumber() != predecessorHeadSegmentLengthValue->GetValueNumber());
1284-
if(predecessorHeadSegmentLengthValue->GetValueInfo() != mergedHeadSegmentLengthValue->GetValueInfo())
1286+
successorBlockData.liveVarSyms->Set(mergedHeadSegmentLengthSym->m_id);
1287+
Value *const mergedHeadSegmentLengthValue = successorBlockData.FindValue(mergedHeadSegmentLengthSym);
1288+
if(mergedHeadSegmentLengthValue)
12851289
{
1286-
mergedHeadSegmentLengthValue->SetValueInfo(
1287-
ValueInfo::MergeLikelyIntValueInfo(
1288-
this->alloc,
1289-
mergedHeadSegmentLengthValue,
1290-
predecessorHeadSegmentLengthValue,
1291-
mergedHeadSegmentLengthValue->GetValueInfo()->Type()
1292-
.Merge(predecessorHeadSegmentLengthValue->GetValueInfo()->Type())));
1290+
Assert(mergedHeadSegmentLengthValue->GetValueNumber() != predecessorHeadSegmentLengthValue->GetValueNumber());
1291+
if(predecessorHeadSegmentLengthValue->GetValueInfo() != mergedHeadSegmentLengthValue->GetValueInfo())
1292+
{
1293+
mergedHeadSegmentLengthValue->SetValueInfo(
1294+
ValueInfo::MergeLikelyIntValueInfo(
1295+
this->alloc,
1296+
mergedHeadSegmentLengthValue,
1297+
predecessorHeadSegmentLengthValue,
1298+
mergedHeadSegmentLengthValue->GetValueInfo()->Type()
1299+
.Merge(predecessorHeadSegmentLengthValue->GetValueInfo()->Type())));
1300+
}
1301+
}
1302+
else
1303+
{
1304+
successorBlockData.SetValue(CopyValue(predecessorHeadSegmentLengthValue), mergedHeadSegmentLengthSym);
12931305
}
1294-
}
1295-
else
1296-
{
1297-
successorBlockData.SetValue(CopyValue(predecessorHeadSegmentLengthValue), mergedHeadSegmentLengthSym);
12981306
}
12991307
}
13001308

@@ -1315,27 +1323,31 @@ void GlobOpt::InsertValueCompensation(
13151323
// Merge the length value
13161324
Assert(predecessorBlockData.liveVarSyms->Test(predecessorLengthSym->m_id));
13171325
predecessorBlockData.liveVarSyms->Set(mergedLengthSym->m_id);
1318-
successorBlockData.liveVarSyms->Set(mergedLengthSym->m_id);
13191326
Value *const predecessorLengthValue = predecessorBlockData.FindValue(predecessorLengthSym);
13201327
Assert(predecessorLengthValue);
13211328
predecessorBlockData.SetValue(predecessorLengthValue, mergedLengthSym);
1322-
Value *const mergedLengthValue = successorBlockData.FindValue(mergedLengthSym);
1323-
if(mergedLengthValue)
1329+
1330+
if (updateSuccessorBlockData)
13241331
{
1325-
Assert(mergedLengthValue->GetValueNumber() != predecessorLengthValue->GetValueNumber());
1326-
if(predecessorLengthValue->GetValueInfo() != mergedLengthValue->GetValueInfo())
1332+
successorBlockData.liveVarSyms->Set(mergedLengthSym->m_id);
1333+
Value *const mergedLengthValue = successorBlockData.FindValue(mergedLengthSym);
1334+
if(mergedLengthValue)
13271335
{
1328-
mergedLengthValue->SetValueInfo(
1329-
ValueInfo::MergeLikelyIntValueInfo(
1330-
this->alloc,
1331-
mergedLengthValue,
1332-
predecessorLengthValue,
1333-
mergedLengthValue->GetValueInfo()->Type().Merge(predecessorLengthValue->GetValueInfo()->Type())));
1336+
Assert(mergedLengthValue->GetValueNumber() != predecessorLengthValue->GetValueNumber());
1337+
if(predecessorLengthValue->GetValueInfo() != mergedLengthValue->GetValueInfo())
1338+
{
1339+
mergedLengthValue->SetValueInfo(
1340+
ValueInfo::MergeLikelyIntValueInfo(
1341+
this->alloc,
1342+
mergedLengthValue,
1343+
predecessorLengthValue,
1344+
mergedLengthValue->GetValueInfo()->Type().Merge(predecessorLengthValue->GetValueInfo()->Type())));
1345+
}
1346+
}
1347+
else
1348+
{
1349+
successorBlockData.SetValue(CopyValue(predecessorLengthValue), mergedLengthSym);
13341350
}
1335-
}
1336-
else
1337-
{
1338-
successorBlockData.SetValue(CopyValue(predecessorLengthValue), mergedLengthSym);
13391351
}
13401352
}
13411353

@@ -2116,6 +2128,7 @@ bool GlobOpt::CollectMemcopyStElementI(IR::Instr *instr, Loop *loop)
21162128

21172129
// Consider: Can we remove the count field?
21182130
memcopyInfo->count++;
2131+
AssertOrFailFast(memcopyInfo->count <= 1);
21192132
memcopyInfo->base = baseSymID;
21202133

21212134
return true;
@@ -2277,6 +2290,7 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
22772290
{
22782291
inductionVariableChangeInfo.unroll++;
22792292
}
2293+
22802294
inductionVariableChangeInfo.isIncremental = isIncr;
22812295
loop->memOpInfo->inductionVariableChangeInfoMap->Item(inductionSymID, inductionVariableChangeInfo);
22822296
if (sym->m_id != inductionSymID)
@@ -17007,6 +17021,7 @@ GlobOpt::GetOrGenerateLoopCountForMemOp(Loop *loop)
1700717021
IR::Opnd *
1700817022
GlobOpt::GenerateInductionVariableChangeForMemOp(Loop *loop, byte unroll, IR::Instr *insertBeforeInstr)
1700917023
{
17024+
AssertOrFailFast(unroll != Js::Constants::InvalidLoopUnrollFactor);
1701017025
LoopCount *loopCount = loop->loopCount;
1701117026
IR::Opnd *sizeOpnd = nullptr;
1701217027
Assert(loopCount);

lib/Backend/Opnd.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,9 +801,17 @@ class PropertySymOpnd sealed : public SymOpnd
801801
return this->monoGuardType;
802802
}
803803

804-
void SetMonoGuardType(JITTypeHolder type)
804+
bool SetMonoGuardType(JITTypeHolder type)
805805
{
806+
if (!(this->monoGuardType == nullptr || this->monoGuardType == type) ||
807+
!((HasEquivalentTypeSet() && GetEquivalentTypeSet()->Contains(type)) ||
808+
(!HasEquivalentTypeSet() && GetType() == type)))
809+
{
810+
// Required type is not in the available set, or we already set the type to something else. Inform the caller.
811+
return false;
812+
}
806813
this->monoGuardType = type;
814+
return true;
807815
}
808816

809817
bool NeedsMonoCheck() const

lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// NOTE: If there is a merge conflict the correct fix is to make a new GUID.
66
// This file was generated with tools\update_bytecode_version.ps1
77

8-
// {3096A219-129D-4A4A-A61C-186D03BB25B7}
8+
// {81AEEA4B-AE4E-40C0-848F-6DB7C5F49F55}
99
const GUID byteCodeCacheReleaseFileVersion =
10-
{ 0x3096a219, 0x129d, 0x4a4a, { 0xa6, 0x1c, 0x18, 0x6d, 0x3, 0xbb, 0x25, 0xb7 } };
10+
{ 0x81AEEA4B, 0xAE4E, 0x40C0, { 0x84, 0x8F, 0x6D, 0xB7, 0xC5, 0xF4, 0x9F, 0x55 } };

lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
var Symbol = platform.Symbol;
1414
var CreateObject = platform.builtInJavascriptObjectEntryCreate;
1515

16+
let FunctionsEnum = {
17+
ArrayValues: setPrototype({ className: "Array", methodName: "values", argumentsCount: 0, forceInline: true /*optional*/, alias: "Symbol.iterator" }, null),
18+
ArrayKeys: setPrototype({ className: "Array", methodName: "keys", argumentsCount: 0, forceInline: true /*optional*/ }, null),
19+
ArrayEntries: setPrototype({ className: "Array", methodName: "entries", argumentsCount: 0, forceInline: true /*optional*/ }, null),
20+
ArrayIndexOf: setPrototype({ className: "Array", methodName: "indexOf", argumentsCount: 1, forceInline: true /*optional*/ }, null),
21+
ArrayFilter: setPrototype({ className: "Array", methodName: "filter", argumentsCount: 1, forceInline: true /*optional*/ }, null),
22+
};
23+
1624
platform.registerChakraLibraryFunction("ArrayIterator", function (arrayObj, iterationKind) {
1725
__chakraLibrary.InitInternalProperties(this, 4, "__$arrayObj$__", "__$nextIndex$__", "__$kind$__", "__$internalDone$__");
1826
this.__$arrayObj$__ = arrayObj;

0 commit comments

Comments
 (0)