Skip to content

Commit 7e9a2ee

Browse files
committed
[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 c5297b8 + edf5eee commit 7e9a2ee

17 files changed

+1529
-1438
lines changed

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +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/
42+
Build/VCBuild*/
4643
buildchk.*
4744
buildfre.*
4845
out/

Build/NuGet/.pack-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.11.12
1+
1.11.13

lib/Backend/BackwardPass.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5422,7 +5422,14 @@ BackwardPass::TrackObjTypeSpecProperties(IR::PropertySymOpnd *opnd, BasicBlock *
54225422
// Some instr protected by this one requires a monomorphic type check. (E.g., final type opt,
54235423
// fixed field not loaded from prototype.) Note the IsTypeAvailable test above: only do this at
54245424
// the initial type check that protects this path.
5425-
opnd->SetMonoGuardType(bucket->GetMonoGuardType());
5425+
if (!opnd->SetMonoGuardType(bucket->GetMonoGuardType()))
5426+
{
5427+
// We can't safely check for the required type here. Clear the objtypespec info to disable optimization
5428+
// using this inline cache, since there appears to be a mismatch, and re-jit.
5429+
// (Dead store pass is too late to generate the bailout points we need to use this type correctly.)
5430+
this->currentInstr->m_func->ClearObjTypeSpecFldInfo(opnd->m_inlineCacheIndex);
5431+
throw Js::RejitException(RejitReason::FailedEquivalentTypeCheck);
5432+
}
54265433
this->currentInstr->ChangeEquivalentToMonoTypeCheckBailOut();
54275434
}
54285435
bucket->SetMonoGuardType(nullptr);
@@ -8742,7 +8749,7 @@ BackwardPass::RestoreInductionVariableValuesAfterMemOp(Loop *loop)
87428749
StackSym *sym = localFunc->m_symTable->FindStackSym(symId)->GetInt32EquivSym(localFunc);
87438750

87448751
IR::Opnd *inductionVariableOpnd = IR::RegOpnd::New(sym, IRType::TyInt32, localFunc);
8745-
IR::Opnd *sizeOpnd = globOpt->GenerateInductionVariableChangeForMemOp(loop, inductionVariableChangeInfo.unroll);
8752+
IR::Opnd *sizeOpnd = globOpt->GenerateInductionVariableChangeForMemOp(loop, inductionVariableChangeInfo.unroll, loop->memOpInfo->instr);
87468753
IR::Instr* restoreInductionVarInstr = IR::Instr::New(opCode, inductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc());
87478754

87488755
// The IR that restores the induction variable's value is placed before the MemOp. Since this IR can

lib/Backend/Func.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ Func::Codegen(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
348348
case RejitReason::MemOpDisabled:
349349
outputData->disableMemOp = TRUE;
350350
break;
351+
case RejitReason::FailedEquivalentTypeCheck:
352+
// No disable flag. The thrower of the re-jit exception must guarantee that objtypespec is disabled where appropriate.
353+
break;
351354
default:
352355
Assume(UNREACHED);
353356
}
@@ -1521,6 +1524,12 @@ Func::GetObjTypeSpecFldInfo(const uint index) const
15211524
return GetWorkItem()->GetJITTimeInfo()->GetObjTypeSpecFldInfo(index);
15221525
}
15231526

1527+
void
1528+
Func::ClearObjTypeSpecFldInfo(const uint index)
1529+
{
1530+
GetWorkItem()->GetJITTimeInfo()->ClearObjTypeSpecFldInfo(index);
1531+
}
1532+
15241533
ObjTypeSpecFldInfo*
15251534
Func::GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const
15261535
{

lib/Backend/Func.h

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

581581
ObjTypeSpecFldInfo* GetObjTypeSpecFldInfo(const uint index) const;
582+
void ClearObjTypeSpecFldInfo(const uint index);
582583
ObjTypeSpecFldInfo* GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const;
583584

584585
// 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
@@ -311,6 +311,18 @@ FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
311311
return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.objTypeSpecFldInfoArray[index]);
312312
}
313313

314+
void
315+
FunctionJITTimeInfo::ClearObjTypeSpecFldInfo(uint index)
316+
{
317+
if (m_data.objTypeSpecFldInfoArray == nullptr)
318+
{
319+
return;
320+
}
321+
AssertOrFailFast(index < m_data.objTypeSpecFldInfoCount);
322+
323+
m_data.objTypeSpecFldInfoArray[index] = nullptr;
324+
}
325+
314326
ObjTypeSpecFldInfo *
315327
FunctionJITTimeInfo::GetGlobalObjTypeSpecFldInfo(uint index) const
316328
{

lib/Backend/FunctionJITTimeInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class FunctionJITTimeInfo
3838
const BVFixed * GetInlineesBV() const;
3939
const FunctionJITTimeInfo * GetJitTimeDataFromFunctionInfoAddr(intptr_t polyFuncInfo) const;
4040
ObjTypeSpecFldInfo * GetObjTypeSpecFldInfo(uint index) const;
41+
void ClearObjTypeSpecFldInfo(uint index);
4142
ObjTypeSpecFldInfo * GetGlobalObjTypeSpecFldInfo(uint index) const;
4243
uint GetGlobalObjTypeSpecFldInfoCount() const;
4344
const FunctionJITRuntimeInfo * GetInlineeForTargetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId, intptr_t inlineeFuncBodyAddr) const;

lib/Backend/GlobOpt.cpp

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,10 @@ void GlobOpt::InsertValueCompensation(
11671167
IR::Instr *insertBeforeInstr = predecessor->GetLastInstr();
11681168
Func *const func = insertBeforeInstr->m_func;
11691169
bool setLastInstrInPredecessor;
1170+
// If this is a loop back edge, and the successor has been completed, don't attempt to update its block data.
1171+
// The update is unnecessary, and the data has likely been freed.
1172+
bool updateSuccessorBlockData = !this->isPerformingLoopBackEdgeCompensation || successor->GetDataUseCount() > 0;
1173+
11701174
if(insertBeforeInstr->IsBranchInstr() || insertBeforeInstr->m_opcode == Js::OpCode::BailTarget)
11711175
{
11721176
// Don't insert code between the branch and the corresponding ByteCodeUses instructions
@@ -1257,29 +1261,33 @@ void GlobOpt::InsertValueCompensation(
12571261
// Merge the head segment length value
12581262
Assert(predecessorBlockData.liveVarSyms->Test(predecessorHeadSegmentLengthSym->m_id));
12591263
predecessorBlockData.liveVarSyms->Set(mergedHeadSegmentLengthSym->m_id);
1260-
successorBlockData.liveVarSyms->Set(mergedHeadSegmentLengthSym->m_id);
12611264
Value *const predecessorHeadSegmentLengthValue =
12621265
predecessorBlockData.FindValue(predecessorHeadSegmentLengthSym);
12631266
Assert(predecessorHeadSegmentLengthValue);
12641267
predecessorBlockData.SetValue(predecessorHeadSegmentLengthValue, mergedHeadSegmentLengthSym);
1265-
Value *const mergedHeadSegmentLengthValue = successorBlockData.FindValue(mergedHeadSegmentLengthSym);
1266-
if(mergedHeadSegmentLengthValue)
1268+
1269+
if (updateSuccessorBlockData)
12671270
{
1268-
Assert(mergedHeadSegmentLengthValue->GetValueNumber() != predecessorHeadSegmentLengthValue->GetValueNumber());
1269-
if(predecessorHeadSegmentLengthValue->GetValueInfo() != mergedHeadSegmentLengthValue->GetValueInfo())
1271+
successorBlockData.liveVarSyms->Set(mergedHeadSegmentLengthSym->m_id);
1272+
Value *const mergedHeadSegmentLengthValue = successorBlockData.FindValue(mergedHeadSegmentLengthSym);
1273+
if(mergedHeadSegmentLengthValue)
12701274
{
1271-
mergedHeadSegmentLengthValue->SetValueInfo(
1272-
ValueInfo::MergeLikelyIntValueInfo(
1273-
this->alloc,
1274-
mergedHeadSegmentLengthValue,
1275-
predecessorHeadSegmentLengthValue,
1276-
mergedHeadSegmentLengthValue->GetValueInfo()->Type()
1277-
.Merge(predecessorHeadSegmentLengthValue->GetValueInfo()->Type())));
1275+
Assert(mergedHeadSegmentLengthValue->GetValueNumber() != predecessorHeadSegmentLengthValue->GetValueNumber());
1276+
if(predecessorHeadSegmentLengthValue->GetValueInfo() != mergedHeadSegmentLengthValue->GetValueInfo())
1277+
{
1278+
mergedHeadSegmentLengthValue->SetValueInfo(
1279+
ValueInfo::MergeLikelyIntValueInfo(
1280+
this->alloc,
1281+
mergedHeadSegmentLengthValue,
1282+
predecessorHeadSegmentLengthValue,
1283+
mergedHeadSegmentLengthValue->GetValueInfo()->Type()
1284+
.Merge(predecessorHeadSegmentLengthValue->GetValueInfo()->Type())));
1285+
}
1286+
}
1287+
else
1288+
{
1289+
successorBlockData.SetValue(CopyValue(predecessorHeadSegmentLengthValue), mergedHeadSegmentLengthSym);
12781290
}
1279-
}
1280-
else
1281-
{
1282-
successorBlockData.SetValue(CopyValue(predecessorHeadSegmentLengthValue), mergedHeadSegmentLengthSym);
12831291
}
12841292
}
12851293

@@ -1300,27 +1308,31 @@ void GlobOpt::InsertValueCompensation(
13001308
// Merge the length value
13011309
Assert(predecessorBlockData.liveVarSyms->Test(predecessorLengthSym->m_id));
13021310
predecessorBlockData.liveVarSyms->Set(mergedLengthSym->m_id);
1303-
successorBlockData.liveVarSyms->Set(mergedLengthSym->m_id);
13041311
Value *const predecessorLengthValue = predecessorBlockData.FindValue(predecessorLengthSym);
13051312
Assert(predecessorLengthValue);
13061313
predecessorBlockData.SetValue(predecessorLengthValue, mergedLengthSym);
1307-
Value *const mergedLengthValue = successorBlockData.FindValue(mergedLengthSym);
1308-
if(mergedLengthValue)
1314+
1315+
if (updateSuccessorBlockData)
13091316
{
1310-
Assert(mergedLengthValue->GetValueNumber() != predecessorLengthValue->GetValueNumber());
1311-
if(predecessorLengthValue->GetValueInfo() != mergedLengthValue->GetValueInfo())
1317+
successorBlockData.liveVarSyms->Set(mergedLengthSym->m_id);
1318+
Value *const mergedLengthValue = successorBlockData.FindValue(mergedLengthSym);
1319+
if(mergedLengthValue)
13121320
{
1313-
mergedLengthValue->SetValueInfo(
1314-
ValueInfo::MergeLikelyIntValueInfo(
1315-
this->alloc,
1316-
mergedLengthValue,
1317-
predecessorLengthValue,
1318-
mergedLengthValue->GetValueInfo()->Type().Merge(predecessorLengthValue->GetValueInfo()->Type())));
1321+
Assert(mergedLengthValue->GetValueNumber() != predecessorLengthValue->GetValueNumber());
1322+
if(predecessorLengthValue->GetValueInfo() != mergedLengthValue->GetValueInfo())
1323+
{
1324+
mergedLengthValue->SetValueInfo(
1325+
ValueInfo::MergeLikelyIntValueInfo(
1326+
this->alloc,
1327+
mergedLengthValue,
1328+
predecessorLengthValue,
1329+
mergedLengthValue->GetValueInfo()->Type().Merge(predecessorLengthValue->GetValueInfo()->Type())));
1330+
}
1331+
}
1332+
else
1333+
{
1334+
successorBlockData.SetValue(CopyValue(predecessorLengthValue), mergedLengthSym);
13191335
}
1320-
}
1321-
else
1322-
{
1323-
successorBlockData.SetValue(CopyValue(predecessorLengthValue), mergedLengthSym);
13241336
}
13251337
}
13261338

@@ -2087,6 +2099,7 @@ bool GlobOpt::CollectMemcopyStElementI(IR::Instr *instr, Loop *loop)
20872099

20882100
// Consider: Can we remove the count field?
20892101
memcopyInfo->count++;
2102+
AssertOrFailFast(memcopyInfo->count <= 1);
20902103
memcopyInfo->base = baseSymID;
20912104

20922105
return true;
@@ -2226,7 +2239,14 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
22262239
{
22272240
Loop::InductionVariableChangeInfo inductionVariableChangeInfo = { 0, 0 };
22282241
inductionVariableChangeInfo = loop->memOpInfo->inductionVariableChangeInfoMap->Lookup(inductionSymID, inductionVariableChangeInfo);
2229-
inductionVariableChangeInfo.unroll++;
2242+
2243+
// If inductionVariableChangeInfo.unroll has been invalidated, do
2244+
// not modify the Js::Constants::InvalidLoopUnrollFactor value
2245+
if (inductionVariableChangeInfo.unroll != Js::Constants::InvalidLoopUnrollFactor)
2246+
{
2247+
inductionVariableChangeInfo.unroll++;
2248+
}
2249+
22302250
inductionVariableChangeInfo.isIncremental = isIncr;
22312251
loop->memOpInfo->inductionVariableChangeInfoMap->Item(inductionSymID, inductionVariableChangeInfo);
22322252
}
@@ -16677,6 +16697,7 @@ GlobOpt::GetOrGenerateLoopCountForMemOp(Loop *loop)
1667716697
IR::Opnd *
1667816698
GlobOpt::GenerateInductionVariableChangeForMemOp(Loop *loop, byte unroll, IR::Instr *insertBeforeInstr)
1667916699
{
16700+
AssertOrFailFast(unroll != Js::Constants::InvalidLoopUnrollFactor);
1668016701
LoopCount *loopCount = loop->loopCount;
1668116702
IR::Opnd *sizeOpnd = nullptr;
1668216703
Assert(loopCount);
@@ -16714,11 +16735,12 @@ GlobOpt::GenerateInductionVariableChangeForMemOp(Loop *loop, byte unroll, IR::In
1671416735

1671516736
IR::Opnd *unrollOpnd = IR::IntConstOpnd::New(unroll, type, localFunc);
1671616737

16717-
InsertInstr(IR::Instr::New(Js::OpCode::Mul_I4,
16718-
sizeOpnd,
16719-
loopCountOpnd,
16720-
unrollOpnd,
16721-
localFunc));
16738+
IR::Instr* inductionChangeMultiplier = IR::Instr::New(
16739+
Js::OpCode::Mul_I4, sizeOpnd, loopCountOpnd, unrollOpnd, localFunc);
16740+
16741+
InsertInstr(inductionChangeMultiplier);
16742+
16743+
inductionChangeMultiplier->ConvertToBailOutInstr(loop->bailOutInfo, IR::BailOutOnOverflow);
1672216744

1672316745
}
1672416746
}

lib/Backend/Opnd.h

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

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

807815
bool NeedsMonoCheck() const

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

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

0 commit comments

Comments
 (0)