Skip to content

Commit f8a6b80

Browse files
committed
[1.11>master] [MERGE #6196 @atulkatti] ChakraCore servicing update for July, 2019
Merge pull request #6196 from atulkatti:servicing/1907 This release addresses the following issues: CVE-2019-1001 CVE-2019-1062 CVE-2019-1092 CVE-2019-1103 CVE-2019-1106 CVE-2019-1107
2 parents 5fa1ffe + 75162b7 commit f8a6b80

14 files changed

+124
-21
lines changed

lib/Backend/BackwardPass.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4369,6 +4369,59 @@ BackwardPass::TraceBlockUses(BasicBlock * block, bool isStart)
43694369

43704370
#endif
43714371

4372+
bool
4373+
BackwardPass::UpdateImplicitCallBailOutKind(IR::Instr *const instr, bool needsBailOutOnImplicitCall)
4374+
{
4375+
Assert(instr);
4376+
Assert(instr->HasBailOutInfo());
4377+
4378+
IR::BailOutKind implicitCallBailOutKind = needsBailOutOnImplicitCall ? IR::BailOutOnImplicitCalls : IR::BailOutInvalid;
4379+
4380+
IR::BailOutKind instrBailOutKind = instr->GetBailOutKind();
4381+
if (instrBailOutKind & IR::BailOutMarkTempObject)
4382+
{
4383+
// Remove the mark temp object bit, as we don't need it after the dead store pass
4384+
instrBailOutKind &= ~IR::BailOutMarkTempObject;
4385+
instr->SetBailOutKind(instrBailOutKind);
4386+
4387+
if (!instr->GetBailOutInfo()->canDeadStore)
4388+
{
4389+
return true;
4390+
}
4391+
}
4392+
4393+
const IR::BailOutKind instrImplicitCallBailOutKind = instrBailOutKind & ~IR::BailOutKindBits;
4394+
if(instrImplicitCallBailOutKind == IR::BailOutOnImplicitCallsPreOp)
4395+
{
4396+
if(needsBailOutOnImplicitCall)
4397+
{
4398+
implicitCallBailOutKind = IR::BailOutOnImplicitCallsPreOp;
4399+
}
4400+
}
4401+
else if(instrImplicitCallBailOutKind != IR::BailOutOnImplicitCalls && instrImplicitCallBailOutKind != IR::BailOutInvalid)
4402+
{
4403+
// This bailout kind (the value of 'instrImplicitCallBailOutKind') must guarantee that implicit calls will not happen.
4404+
// If it doesn't make such a guarantee, it must be possible to merge this bailout kind with an implicit call bailout
4405+
// kind, and therefore should be part of BailOutKindBits.
4406+
Assert(!needsBailOutOnImplicitCall);
4407+
return true;
4408+
}
4409+
4410+
if(instrImplicitCallBailOutKind == implicitCallBailOutKind)
4411+
{
4412+
return true;
4413+
}
4414+
4415+
const IR::BailOutKind newBailOutKind = instrBailOutKind - instrImplicitCallBailOutKind + implicitCallBailOutKind;
4416+
if(newBailOutKind == IR::BailOutInvalid)
4417+
{
4418+
return false;
4419+
}
4420+
4421+
instr->SetBailOutKind(newBailOutKind);
4422+
return true;
4423+
}
4424+
43724425
bool
43734426
BackwardPass::ProcessNoImplicitCallUses(IR::Instr *const instr)
43744427
{

lib/Backend/BailOut.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class BailOutInfo
2727
BailOutInfo(uint32 bailOutOffset, Func* bailOutFunc) :
2828
bailOutOffset(bailOutOffset), bailOutFunc(bailOutFunc),
2929
byteCodeUpwardExposedUsed(nullptr), polymorphicCacheIndex((uint)-1), startCallCount(0), startCallInfo(nullptr), bailOutInstr(nullptr),
30-
totalOutParamCount(0), argOutSyms(nullptr), bailOutRecord(nullptr), wasCloned(false), isInvertedBranch(false), sharedBailOutKind(true), isLoopTopBailOutInfo(false),
30+
totalOutParamCount(0), argOutSyms(nullptr), bailOutRecord(nullptr), wasCloned(false), isInvertedBranch(false), sharedBailOutKind(true), isLoopTopBailOutInfo(false), canDeadStore(true),
3131
outParamInlinedArgSlot(nullptr), liveVarSyms(nullptr), liveLosslessInt32Syms(nullptr), liveFloat64Syms(nullptr),
3232
branchConditionOpnd(nullptr),
3333
stackLiteralBailOutInfoCount(0), stackLiteralBailOutInfo(nullptr),
@@ -107,6 +107,7 @@ class BailOutInfo
107107
#endif
108108
bool wasCloned;
109109
bool isInvertedBranch;
110+
bool canDeadStore;
110111
bool sharedBailOutKind;
111112
bool isLoopTopBailOutInfo;
112113

lib/Backend/Func.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ Func::Codegen(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
355355
case RejitReason::TrackIntOverflowDisabled:
356356
outputData->disableTrackCompoundedIntOverflow = TRUE;
357357
break;
358+
case RejitReason::MemOpDisabled:
359+
outputData->disableMemOp = TRUE;
360+
break;
358361
default:
359362
Assume(UNREACHED);
360363
}
@@ -1112,6 +1115,12 @@ Func::IsTrackCompoundedIntOverflowDisabled() const
11121115
return (HasProfileInfo() && GetReadOnlyProfileInfo()->IsTrackCompoundedIntOverflowDisabled()) || m_output.IsTrackCompoundedIntOverflowDisabled();
11131116
}
11141117

1118+
bool
1119+
Func::IsMemOpDisabled() const
1120+
{
1121+
return (HasProfileInfo() && GetReadOnlyProfileInfo()->IsMemOpDisabled()) || m_output.IsMemOpDisabled();
1122+
}
1123+
11151124
bool
11161125
Func::IsArrayCheckHoistDisabled() const
11171126
{

lib/Backend/Func.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
967967
bool HasStackSymForFormal(Js::ArgSlot formalsIndex);
968968

969969
bool IsTrackCompoundedIntOverflowDisabled() const;
970+
bool IsMemOpDisabled() const;
970971
bool IsArrayCheckHoistDisabled() const;
971972
bool IsStackArgOptDisabled() const;
972973
bool IsSwitchOptDisabled() const;

lib/Backend/GlobOpt.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,7 +2675,7 @@ GlobOpt::OptInstr(IR::Instr *&instr, bool* isInstrRemoved)
26752675
!(instr->IsJitProfilingInstr()) &&
26762676
this->currentBlock->loop && !IsLoopPrePass() &&
26772677
!func->IsJitInDebugMode() &&
2678-
(func->HasProfileInfo() && !func->GetReadOnlyProfileInfo()->IsMemOpDisabled()) &&
2678+
!func->IsMemOpDisabled() &&
26792679
this->currentBlock->loop->doMemOp)
26802680
{
26812681
CollectMemOpInfo(instrPrev, instr, src1Val, src2Val);
@@ -16864,6 +16864,7 @@ GlobOpt::GenerateBailOutMarkTempObjectIfNeeded(IR::Instr * instr, IR::Opnd * opn
1686416864
if (instr->HasBailOutInfo())
1686516865
{
1686616866
instr->SetBailOutKind(instr->GetBailOutKind() | IR::BailOutMarkTempObject);
16867+
instr->GetBailOutInfo()->canDeadStore = false;
1686716868
}
1686816869
else
1686916870
{
@@ -16873,6 +16874,11 @@ GlobOpt::GenerateBailOutMarkTempObjectIfNeeded(IR::Instr * instr, IR::Opnd * opn
1687316874
|| (instr->m_opcode == Js::OpCode::FromVar && !opnd->GetValueType().IsPrimitive())
1687416875
|| propertySymOpnd == nullptr
1687516876
|| !propertySymOpnd->IsTypeCheckProtected())
16877+
{
16878+
this->GenerateBailAtOperation(&instr, IR::BailOutMarkTempObject);
16879+
instr->GetBailOutInfo()->canDeadStore = false;
16880+
}
16881+
else if (propertySymOpnd->MayHaveImplicitCall())
1687616882
{
1687716883
this->GenerateBailAtOperation(&instr, IR::BailOutMarkTempObject);
1687816884
}
@@ -17013,7 +17019,14 @@ GlobOpt::GenerateInductionVariableChangeForMemOp(Loop *loop, byte unroll, IR::In
1701317019
}
1701417020
else
1701517021
{
17016-
uint size = (loopCount->LoopCountMinusOneConstantValue() + 1) * unroll;
17022+
int32 loopCountMinusOnePlusOne;
17023+
int32 size;
17024+
if (Int32Math::Add(loopCount->LoopCountMinusOneConstantValue(), 1, &loopCountMinusOnePlusOne) ||
17025+
Int32Math::Mul(loopCountMinusOnePlusOne, unroll, &size))
17026+
{
17027+
throw Js::RejitException(RejitReason::MemOpDisabled);
17028+
}
17029+
Assert(size > 0);
1701717030
sizeOpnd = IR::IntConstOpnd::New(size, IRType::TyUint32, localFunc);
1701817031
}
1701917032
loop->memOpInfo->inductionVariableOpndPerUnrollMap->Add(unroll, sizeOpnd);

lib/Backend/GlobOptBlockData.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,8 @@ GlobOptBlockData::MergeValueInfo(
974974
fromDataValueInfo->AsArrayValueInfo(),
975975
fromDataSym,
976976
symsRequiringCompensation,
977-
symsCreatedForMerge);
977+
symsCreatedForMerge,
978+
isLoopBackEdge);
978979
}
979980

980981
// Consider: If both values are VarConstantValueInfo with the same value, we could
@@ -1072,7 +1073,8 @@ ValueInfo *GlobOptBlockData::MergeArrayValueInfo(
10721073
const ArrayValueInfo *const fromDataValueInfo,
10731074
Sym *const arraySym,
10741075
BVSparse<JitArenaAllocator> *const symsRequiringCompensation,
1075-
BVSparse<JitArenaAllocator> *const symsCreatedForMerge)
1076+
BVSparse<JitArenaAllocator> *const symsCreatedForMerge,
1077+
bool isLoopBackEdge)
10761078
{
10771079
Assert(mergedValueType.IsAnyOptimizedArray());
10781080
Assert(toDataValueInfo);
@@ -1095,7 +1097,7 @@ ValueInfo *GlobOptBlockData::MergeArrayValueInfo(
10951097
}
10961098
else
10971099
{
1098-
if (!this->globOpt->IsLoopPrePass())
1100+
if (!this->globOpt->IsLoopPrePass() && !isLoopBackEdge)
10991101
{
11001102
// Adding compensation code in the prepass won't help, as the symstores would again be different in the main pass.
11011103
Assert(symsRequiringCompensation);
@@ -1123,7 +1125,7 @@ ValueInfo *GlobOptBlockData::MergeArrayValueInfo(
11231125
}
11241126
else
11251127
{
1126-
if (!this->globOpt->IsLoopPrePass())
1128+
if (!this->globOpt->IsLoopPrePass() && !isLoopBackEdge)
11271129
{
11281130
Assert(symsRequiringCompensation);
11291131
symsRequiringCompensation->Set(arraySym->m_id);
@@ -1150,7 +1152,7 @@ ValueInfo *GlobOptBlockData::MergeArrayValueInfo(
11501152
}
11511153
else
11521154
{
1153-
if (!this->globOpt->IsLoopPrePass())
1155+
if (!this->globOpt->IsLoopPrePass() && !isLoopBackEdge)
11541156
{
11551157
Assert(symsRequiringCompensation);
11561158
symsRequiringCompensation->Set(arraySym->m_id);

lib/Backend/GlobOptBlockData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ class GlobOptBlockData
264264
Value * MergeValues(Value *toDataValue, Value *fromDataValue, Sym *fromDataSym, bool isLoopBackEdge, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
265265
ValueInfo * MergeValueInfo(Value *toDataVal, Value *fromDataVal, Sym *fromDataSym, bool isLoopBackEdge, bool sameValueNumber, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
266266
JsTypeValueInfo * MergeJsTypeValueInfo(JsTypeValueInfo * toValueInfo, JsTypeValueInfo * fromValueInfo, bool isLoopBackEdge, bool sameValueNumber);
267-
ValueInfo * MergeArrayValueInfo(const ValueType mergedValueType, const ArrayValueInfo *const toDataValueInfo, const ArrayValueInfo *const fromDataValueInfo, Sym *const arraySym, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
267+
ValueInfo * MergeArrayValueInfo(const ValueType mergedValueType, const ArrayValueInfo *const toDataValueInfo, const ArrayValueInfo *const fromDataValueInfo, Sym *const arraySym, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge, bool isLoopBackEdge);
268268

269269
// Argument Tracking
270270
public:

lib/Backend/GlobOptFields.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,14 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
409409
if (inGlobOpt)
410410
{
411411
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
412+
if (this->objectTypeSyms)
413+
{
414+
if (this->currentBlock->globOptData.maybeWrittenTypeSyms == nullptr)
415+
{
416+
this->currentBlock->globOptData.maybeWrittenTypeSyms = JitAnew(this->alloc, BVSparse<JitArenaAllocator>, this->alloc);
417+
}
418+
this->currentBlock->globOptData.maybeWrittenTypeSyms->Or(this->objectTypeSyms);
419+
}
412420
}
413421

414422
// fall through

lib/Backend/JITOutput.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ JITOutput::IsTrackCompoundedIntOverflowDisabled() const
6565
return m_outputData->disableTrackCompoundedIntOverflow != FALSE;
6666
}
6767

68+
bool
69+
JITOutput::IsMemOpDisabled() const
70+
{
71+
return m_outputData->disableMemOp != FALSE;
72+
}
73+
6874
bool
6975
JITOutput::IsArrayCheckHoistDisabled() const
7076
{

lib/Backend/JITOutput.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class JITOutput
2222
void RecordXData(BYTE * xdata);
2323
#endif
2424
bool IsTrackCompoundedIntOverflowDisabled() const;
25+
bool IsMemOpDisabled() const;
2526
bool IsArrayCheckHoistDisabled() const;
2627
bool IsStackArgOptDisabled() const;
2728
bool IsSwitchOptDisabled() const;

lib/Backend/NativeCodeGenerator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,10 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
12341234
{
12351235
body->GetAnyDynamicProfileInfo()->DisableTrackCompoundedIntOverflow();
12361236
}
1237+
if (jitWriteData.disableMemOp)
1238+
{
1239+
body->GetAnyDynamicProfileInfo()->DisableMemOp();
1240+
}
12371241
}
12381242

12391243
if (jitWriteData.disableInlineApply)

lib/Backend/Opnd.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,8 @@ PropertySymOpnd::IsObjectHeaderInlined() const
962962
bool
963963
PropertySymOpnd::ChangesObjectLayout() const
964964
{
965-
JITTypeHolder cachedType = this->IsMono() ? this->GetType() : this->GetFirstEquivalentType();
965+
JITTypeHolder cachedType = this->HasInitialType() ? this->GetInitialType() :
966+
this->IsMono() ? this->GetType() : this->GetFirstEquivalentType();
966967

967968
JITTypeHolder finalType = this->GetFinalType();
968969

@@ -987,13 +988,11 @@ PropertySymOpnd::ChangesObjectLayout() const
987988
// This is the case where the type transition actually occurs. (This is the only case that's detectable
988989
// during the loop pre-pass, since final types are not in place yet.)
989990

990-
Assert(cachedType != nullptr && Js::DynamicType::Is(cachedType->GetTypeId()));
991-
992-
const JITTypeHandler * cachedTypeHandler = cachedType->GetTypeHandler();
993991
const JITTypeHandler * initialTypeHandler = initialType->GetTypeHandler();
994992

995-
return cachedTypeHandler->GetInlineSlotCapacity() != initialTypeHandler->GetInlineSlotCapacity() ||
996-
cachedTypeHandler->GetOffsetOfInlineSlots() != initialTypeHandler->GetOffsetOfInlineSlots();
993+
// If no final type has been set in the forward pass, then we have no way of knowing how the object shape will evolve here.
994+
// If the initial type is object-header-inlined, assume that the layout may change.
995+
return initialTypeHandler->IsObjectHeaderInlinedTypeHandler();
997996
}
998997

999998
return false;

lib/Backend/Opnd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,8 @@ class PropertySymOpnd sealed : public SymOpnd
11621162
// fall back on live cache. Similarly, for fixed method checks.
11631163
bool MayHaveImplicitCall() const
11641164
{
1165-
return !IsRootObjectNonConfigurableFieldLoad() && !UsesFixedValue() && (!IsTypeCheckSeqCandidate() || !IsTypeCheckProtected());
1165+
return !IsRootObjectNonConfigurableFieldLoad() && !UsesFixedValue() && (!IsTypeCheckSeqCandidate() || !IsTypeCheckProtected()
1166+
|| (IsLoadedFromProto() && NeedsWriteGuardTypeCheck()));
11661167
}
11671168

11681169
// Is the instruction involving this operand part of a type check sequence? This is different from IsObjTypeSpecOptimized

lib/JITIDL/JITTypes.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -847,37 +847,42 @@ typedef struct JITOutputIDL
847847
boolean disableStackArgOpt;
848848
boolean disableSwitchOpt;
849849
boolean disableTrackCompoundedIntOverflow;
850-
boolean isInPrereservedRegion;
850+
boolean disableMemOp;
851851

852+
boolean isInPrereservedRegion;
852853
boolean hasBailoutInstr;
853-
854854
boolean hasJittedStackClosure;
855+
IDL_PAD1(0)
855856

856857
unsigned short pdataCount;
857858
unsigned short xdataSize;
858859

859860
unsigned short argUsedForBranch;
861+
IDL_PAD2(1)
860862

861863
int localVarSlotsOffset; // FunctionEntryPointInfo only
864+
862865
int localVarChangedOffset; // FunctionEntryPointInfo only
863866
unsigned int frameHeight;
864867

865-
866868
unsigned int codeSize;
867869
unsigned int throwMapOffset;
870+
868871
unsigned int throwMapCount;
869872
unsigned int inlineeFrameOffsetArrayOffset;
870-
unsigned int inlineeFrameOffsetArrayCount;
871873

874+
unsigned int inlineeFrameOffsetArrayCount;
872875
unsigned int propertyGuardCount;
876+
873877
unsigned int ctorCachesCount;
878+
X64_PAD4(2)
874879

875880
#if TARGET_64
876881
CHAKRA_PTR xdataAddr;
877882
#elif defined(_M_ARM)
878883
unsigned int xdataOffset;
879884
#else
880-
X86_PAD4(0)
885+
X86_PAD4(3)
881886
#endif
882887
CHAKRA_PTR codeAddress;
883888
CHAKRA_PTR thunkAddress;

0 commit comments

Comments
 (0)