Skip to content

Commit d797e3f

Browse files
committed
[MERGE #6122 @MikeHolman] May 2019 Security Update
Merge pull request #6122 from pr/MikeHolman/servicing/1905 May 2019 Security Update that addresses the following issues in ChakraCore: CVE-2019-0911 CVE-2019-0912 CVE-2019-0913 CVE-2019-0914 CVE-2019-0915 CVE-2019-0916 CVE-2019-0917 CVE-2019-0922 CVE-2019-0923 CVE-2019-0924 CVE-2019-0925 CVE-2019-0927 CVE-2019-0933 CVE-2019-0937
2 parents ea04913 + 4594e34 commit d797e3f

18 files changed

+182
-38
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.8
1+
1.11.9

lib/Backend/BackwardPass.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4677,10 +4677,9 @@ BackwardPass::ProcessNewScObject(IR::Instr* instr)
46774677
return;
46784678
}
46794679

4680-
if (instr->HasBailOutInfo())
4680+
if (instr->HasBailOutInfo() && (instr->GetBailOutKind() & ~IR::BailOutKindBits) == IR::BailOutFailedCtorGuardCheck)
46814681
{
46824682
Assert(instr->IsProfiledInstr());
4683-
Assert(instr->GetBailOutKind() == IR::BailOutFailedCtorGuardCheck);
46844683
Assert(instr->GetDst()->IsRegOpnd());
46854684

46864685
BasicBlock * block = this->currentBlock;

lib/Backend/GlobOpt.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13199,6 +13199,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1319913199
const bool useValueTypes = !IsLoopPrePass(); // Source value types are not guaranteed to be correct in a loop prepass
1320013200
switch(instr->m_opcode)
1320113201
{
13202+
case Js::OpCode::StElemC:
1320213203
case Js::OpCode::StElemI_A:
1320313204
case Js::OpCode::StElemI_A_Strict:
1320413205
{
@@ -13249,8 +13250,13 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1324913250
}
1325013251
break;
1325113252

13253+
case Js::OpCode::ConsoleScopedStFld:
13254+
case Js::OpCode::ConsoleScopedStFldStrict:
13255+
case Js::OpCode::ScopedStFld:
13256+
case Js::OpCode::ScopedStFldStrict:
1325213257
case Js::OpCode::StFld:
1325313258
case Js::OpCode::StFldStrict:
13259+
case Js::OpCode::StSuperFld:
1325413260
{
1325513261
Assert(instr->GetDst());
1325613262

@@ -13462,6 +13468,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1346213468
break;
1346313469

1346413470
case Js::OpCode::NewScObjectNoCtor:
13471+
case Js::OpCode::NewScObjectNoCtorFull:
1346513472
if(doNativeArrayTypeSpec)
1346613473
{
1346713474
// Class/object construction can make something a prototype

lib/Backend/GlobOptArrays.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,14 @@ void GlobOpt::ArraySrcOpt::Optimize()
17361736
{
17371737
if (newBaseValueType != baseValueType)
17381738
{
1739-
UpdateValue(nullptr, nullptr, nullptr);
1739+
if (globOpt->IsSafeToTransferInPrePass(baseOpnd, baseValue))
1740+
{
1741+
UpdateValue(nullptr, nullptr, nullptr);
1742+
}
1743+
else if (isLikelyJsArray && globOpt->IsOperationThatLikelyKillsJsArraysWithNoMissingValues(instr) && baseValueInfo->HasNoMissingValues())
1744+
{
1745+
globOpt->ChangeValueType(nullptr, baseValue, baseValueInfo->Type().SetHasNoMissingValues(false), true);
1746+
}
17401747
}
17411748

17421749
// For javascript arrays and objects with javascript arrays:

lib/Backend/GlobOptBailOut.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,14 @@ GlobOpt::MayNeedBailOnImplicitCall(IR::Instr const * instr, Value const * src1Va
13371337
);
13381338
}
13391339

1340+
case Js::OpCode::NewScObjectNoCtor:
1341+
if (instr->HasBailOutInfo() && (instr->GetBailOutKind() & ~IR::BailOutKindBits) == IR::BailOutFailedCtorGuardCheck)
1342+
{
1343+
// No helper call with this bailout.
1344+
return false;
1345+
}
1346+
break;
1347+
13401348
default:
13411349
break;
13421350
}

lib/Backend/GlobOptExpr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,20 +814,28 @@ GlobOpt::ProcessArrayValueKills(IR::Instr *instr)
814814
{
815815
switch (instr->m_opcode)
816816
{
817+
case Js::OpCode::StElemC:
817818
case Js::OpCode::StElemI_A:
818819
case Js::OpCode::StElemI_A_Strict:
819820
case Js::OpCode::DeleteElemI_A:
820821
case Js::OpCode::DeleteElemIStrict_A:
822+
case Js::OpCode::ConsoleScopedStFld:
823+
case Js::OpCode::ConsoleScopedStFldStrict:
824+
case Js::OpCode::ScopedStFld:
825+
case Js::OpCode::ScopedStFldStrict:
821826
case Js::OpCode::StFld:
822827
case Js::OpCode::StRootFld:
823828
case Js::OpCode::StFldStrict:
824829
case Js::OpCode::StRootFldStrict:
830+
case Js::OpCode::StSuperFld:
825831
case Js::OpCode::StSlot:
826832
case Js::OpCode::StSlotChkUndecl:
827833
case Js::OpCode::DeleteFld:
828834
case Js::OpCode::DeleteRootFld:
829835
case Js::OpCode::DeleteFldStrict:
830836
case Js::OpCode::DeleteRootFldStrict:
837+
case Js::OpCode::ScopedDeleteFld:
838+
case Js::OpCode::ScopedDeleteFldStrict:
831839
case Js::OpCode::StArrViewElem:
832840
// These array helpers may change A.length (and A[i] could be A.length)...
833841
case Js::OpCode::InlineArrayPush:

lib/Backend/GlobOptFields.cpp

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
335335
IR::JnHelperMethod fnHelper;
336336
switch(instr->m_opcode)
337337
{
338+
case Js::OpCode::StElemC:
338339
case Js::OpCode::StElemI_A:
339340
case Js::OpCode::StElemI_A_Strict:
340341
Assert(dstOpnd != nullptr);
@@ -366,6 +367,8 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
366367
case Js::OpCode::DeleteRootFld:
367368
case Js::OpCode::DeleteFldStrict:
368369
case Js::OpCode::DeleteRootFldStrict:
370+
case Js::OpCode::ScopedDeleteFld:
371+
case Js::OpCode::ScopedDeleteFldStrict:
369372
sym = instr->GetSrc1()->AsSymOpnd()->m_sym;
370373
KillLiveFields(sym->AsPropertySym(), bv);
371374
if (inGlobOpt)
@@ -387,13 +390,36 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
387390
this->KillAllObjectTypes(bv);
388391
}
389392
break;
393+
394+
case Js::OpCode::ConsoleScopedStFld:
395+
case Js::OpCode::ConsoleScopedStFldStrict:
396+
case Js::OpCode::ScopedStFld:
397+
case Js::OpCode::ScopedStFldStrict:
398+
// This is already taken care of for FastFld opcodes
399+
400+
if (inGlobOpt)
401+
{
402+
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
403+
}
404+
405+
// fall through
406+
390407
case Js::OpCode::InitFld:
408+
case Js::OpCode::InitConstFld:
409+
case Js::OpCode::InitLetFld:
410+
case Js::OpCode::InitRootFld:
411+
case Js::OpCode::InitRootConstFld:
412+
case Js::OpCode::InitRootLetFld:
413+
#if !FLOATVAR
414+
case Js::OpCode::StSlotBoxTemp:
415+
#endif
391416
case Js::OpCode::StFld:
392417
case Js::OpCode::StRootFld:
393418
case Js::OpCode::StFldStrict:
394419
case Js::OpCode::StRootFldStrict:
395420
case Js::OpCode::StSlot:
396421
case Js::OpCode::StSlotChkUndecl:
422+
case Js::OpCode::StSuperFld:
397423
Assert(dstOpnd != nullptr);
398424
sym = dstOpnd->AsSymOpnd()->m_sym;
399425
if (inGlobOpt)
@@ -415,11 +441,19 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
415441

416442
case Js::OpCode::InlineArrayPush:
417443
case Js::OpCode::InlineArrayPop:
418-
KillLiveFields(this->lengthEquivBv, bv);
419-
if (inGlobOpt)
444+
if(instr->m_func->GetThisOrParentInlinerHasArguments())
420445
{
421-
// Deleting an item, or pushing a property to a non-array, may change object layout
422-
KillAllObjectTypes(bv);
446+
this->KillAllFields(bv);
447+
this->SetAnyPropertyMayBeWrittenTo();
448+
}
449+
else
450+
{
451+
KillLiveFields(this->lengthEquivBv, bv);
452+
if (inGlobOpt)
453+
{
454+
// Deleting an item, or pushing a property to a non-array, may change object layout
455+
KillAllObjectTypes(bv);
456+
}
423457
}
424458
break;
425459

@@ -444,14 +478,23 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
444478
// Kill length field for built-ins that can update it.
445479
if (nullptr != this->lengthEquivBv)
446480
{
447-
KillLiveFields(this->lengthEquivBv, bv);
481+
// If has arguments, all fields are killed in fall through
482+
if (!instr->m_func->GetThisOrParentInlinerHasArguments())
483+
{
484+
KillLiveFields(this->lengthEquivBv, bv);
485+
}
448486
}
449487
// fall through
450488

451489
case IR::JnHelperMethod::HelperArray_Reverse:
452-
// Deleting an item may change object layout
453-
if (inGlobOpt)
490+
if (instr->m_func->GetThisOrParentInlinerHasArguments())
491+
{
492+
this->KillAllFields(bv);
493+
this->SetAnyPropertyMayBeWrittenTo();
494+
}
495+
else if (inGlobOpt)
454496
{
497+
// Deleting an item may change object layout
455498
KillAllObjectTypes(bv);
456499
}
457500
break;
@@ -492,6 +535,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
492535
case Js::OpCode::InitClass:
493536
case Js::OpCode::InitProto:
494537
case Js::OpCode::NewScObjectNoCtor:
538+
case Js::OpCode::NewScObjectNoCtorFull:
495539
if (inGlobOpt)
496540
{
497541
// Opcodes that make an object into a prototype may break object-header-inlining and final type opt.

lib/Backend/IRBuilder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,7 +1758,7 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
17581758
}
17591759

17601760
case Js::OpCode::NewScObjectSimple:
1761-
dstValueType = ValueType::GetObject(ObjectType::Object);
1761+
dstValueType = ValueType::GetObject(ObjectType::UninitializedObject);
17621762
// fall-through
17631763
case Js::OpCode::LdFuncExpr:
17641764
m_func->DisableCanDoInlineArgOpt();
@@ -5050,7 +5050,7 @@ IRBuilder::BuildAuxiliary(Js::OpCode newOpcode, uint32 offset)
50505050
// lower take it from there...
50515051
srcOpnd = IR::IntConstOpnd::New(auxInsn->Offset, TyUint32, m_func);
50525052
dstOpnd = this->BuildDstOpnd(dstRegSlot);
5053-
dstOpnd->SetValueType(ValueType::GetObject(ObjectType::Object));
5053+
dstOpnd->SetValueType(ValueType::GetObject(ObjectType::UninitializedObject));
50545054
instr = IR::Instr::New(newOpcode, dstOpnd, srcOpnd, m_func);
50555055

50565056
// Because we're going to be making decisions based off the value, we have to defer

lib/Backend/Inline.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4204,6 +4204,8 @@ Inline::SplitConstructorCallCommon(
42044204
{
42054205
createObjInstr->SetByteCodeOffset(newObjInstr);
42064206
createObjInstr->GetSrc1()->SetIsJITOptimizedReg(true);
4207+
// We're splitting a single byte code, so the interpreter has to resume from the beginning if we bail out.
4208+
createObjInstr->forcePreOpBailOutIfNeeded = true;
42074209
newObjInstr->InsertBefore(createObjInstr);
42084210

42094211
createObjDst->SetValueType(ValueType::GetObject(ObjectType::UninitializedObject));

lib/Backend/Lower.cpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4601,18 +4601,40 @@ Lowerer::LowerNewScObject(IR::Instr *newObjInstr, bool callCtor, bool hasArgs, b
46014601
{
46024602
Assert(!newObjDst->CanStoreTemp());
46034603
// createObjDst = NewScObject...(ctorOpnd)
4604-
newScHelper = !callCtor ?
4605-
(isBaseClassConstructorNewScObject ?
4606-
(hasArgs ? IR::HelperNewScObjectNoCtorFull : IR::HelperNewScObjectNoArgNoCtorFull) :
4607-
(hasArgs ? IR::HelperNewScObjectNoCtor : IR::HelperNewScObjectNoArgNoCtor)) :
4608-
(hasArgs || usedFixedCtorCache ? IR::HelperNewScObjectNoCtor : IR::HelperNewScObjectNoArg);
46094604

46104605
LoadScriptContext(newObjInstr);
4611-
m_lowererMD.LoadHelperArgument(newObjInstr, newObjInstr->GetSrc1());
46124606

4613-
newScObjCall = IR::Instr::New(Js::OpCode::Call, createObjDst, IR::HelperCallOpnd::New(newScHelper, func), func);
4614-
newObjInstr->InsertBefore(newScObjCall);
4615-
m_lowererMD.LowerCall(newScObjCall, 0);
4607+
if (callCtor)
4608+
{
4609+
newScHelper = (hasArgs || usedFixedCtorCache ? IR::HelperNewScObjectNoCtor : IR::HelperNewScObjectNoArg);
4610+
4611+
m_lowererMD.LoadHelperArgument(newObjInstr, newObjInstr->GetSrc1());
4612+
4613+
newScObjCall = IR::Instr::New(Js::OpCode::Call, createObjDst, IR::HelperCallOpnd::New(newScHelper, func), func);
4614+
newObjInstr->InsertBefore(newScObjCall);
4615+
m_lowererMD.LowerCall(newScObjCall, 0);
4616+
}
4617+
else
4618+
{
4619+
newScHelper =
4620+
(isBaseClassConstructorNewScObject ?
4621+
(hasArgs ? IR::HelperNewScObjectNoCtorFull : IR::HelperNewScObjectNoArgNoCtorFull) :
4622+
(hasArgs ? IR::HelperNewScObjectNoCtor : IR::HelperNewScObjectNoArgNoCtor));
4623+
4624+
// Branch around the helper call to execute the inlined ctor.
4625+
Assert(callCtorLabel != nullptr);
4626+
newObjInstr->InsertAfter(callCtorLabel);
4627+
4628+
// Change the NewScObject* to a helper call on the spot. This generates implicit call bailout for us if we need one.
4629+
m_lowererMD.LoadHelperArgument(newObjInstr, newObjInstr->UnlinkSrc1());
4630+
m_lowererMD.ChangeToHelperCall(newObjInstr, newScHelper);
4631+
4632+
// Then we're done.
4633+
Assert(createObjDst == newObjDst);
4634+
4635+
// Return the first instruction above the region we've just lowered.
4636+
return RemoveLoweredRegionStartMarker(startMarkerInstr);
4637+
}
46164638
}
46174639
}
46184640

@@ -4857,21 +4879,17 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
48574879
skipNewScObj = false;
48584880
returnNewScObj = false;
48594881

4860-
AssertMsg(!PHASE_OFF(Js::ObjTypeSpecNewObjPhase, this->m_func) || !newObjInstr->HasBailOutInfo(),
4861-
"Why do we have bailout on NewScObject when ObjTypeSpecNewObj is off?");
4862-
48634882
if (PHASE_OFF(Js::FixedNewObjPhase, newObjInstr->m_func) && PHASE_OFF(Js::ObjTypeSpecNewObjPhase, this->m_func))
48644883
{
48654884
return false;
48664885
}
48674886

48684887
JITTimeConstructorCache * ctorCache;
48694888

4870-
if (newObjInstr->HasBailOutInfo())
4889+
if (newObjInstr->HasBailOutInfo() && (newObjInstr->GetBailOutKind() & ~IR::BailOutKindBits) == IR::BailOutFailedCtorGuardCheck)
48714890
{
48724891
Assert(newObjInstr->IsNewScObjectInstr());
48734892
Assert(newObjInstr->IsProfiledInstr());
4874-
Assert(newObjInstr->GetBailOutKind() == IR::BailOutFailedCtorGuardCheck);
48754893

48764894
emitBailOut = true;
48774895

0 commit comments

Comments
 (0)