Skip to content

Commit 0f7e500

Browse files
committed
[MERGE #5936 @MikeHolman] February 2019 Security Update
Merge pull request #5936 from MikeHolman:servicing/1902_1_11 February 2019 Security Update that addresses the following issues in ChakraCore: CVE-2019-0590 CVE-2019-0591 CVE-2019-0593 CVE-2019-0605 CVE-2019-0607 CVE-2019-0610 CVE-2019-0640 CVE-2019-0642 CVE-2019-0644 CVE-2019-0648 CVE-2019-0649 CVE-2019-0651 CVE-2019-0655 CVE-2019-0658
2 parents fe64d93 + a54c9cb commit 0f7e500

24 files changed

+217
-140
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.5
1+
1.11.6

lib/Backend/CodeGenWorkItem.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -210,19 +210,7 @@ void CodeGenWorkItem::OnWorkItemProcessFail(NativeCodeGenerator* codeGen)
210210
#if PDATA_ENABLED & defined(_WIN32)
211211
if (this->entryPointInfo)
212212
{
213-
XDataAllocation * xdataAllocation = this->entryPointInfo->GetNativeEntryPointData()->GetXDataInfo();
214-
if (xdataAllocation)
215-
{
216-
void* functionTable = xdataAllocation->functionTable;
217-
if (functionTable)
218-
{
219-
if (!DelayDeletingFunctionTable::AddEntry(functionTable))
220-
{
221-
PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("[%d]OnWorkItemProcessFail: Failed to add to slist, table: %llx\n"), GetCurrentThreadId(), functionTable);
222-
DelayDeletingFunctionTable::DeleteFunctionTable(functionTable);
223-
}
224-
}
225-
}
213+
this->entryPointInfo->GetNativeEntryPointData()->CleanupXDataInfo();
226214
}
227215
#endif
228216
codeGen->FreeNativeCodeGenAllocation(this->allocation->allocation->address);

lib/Backend/Func.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,14 +1673,14 @@ Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, JITTimeConstructorCac
16731673

16741674
JITTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
16751675
{
1676-
Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
1676+
AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
16771677
Assert(this->constructorCaches != nullptr);
16781678
return this->constructorCaches[profiledCallSiteId];
16791679
}
16801680

16811681
void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, JITTimeConstructorCache* constructorCache)
16821682
{
1683-
Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
1683+
AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
16841684
Assert(constructorCache != nullptr);
16851685
Assert(this->constructorCaches != nullptr);
16861686
Assert(this->constructorCaches[profiledCallSiteId] == nullptr);

lib/Backend/FunctionJITTimeInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,11 @@ FunctionJITTimeInfo::GetRuntimeInfo() const
302302
ObjTypeSpecFldInfo *
303303
FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
304304
{
305-
AssertOrFailFast(index < GetBody()->GetInlineCacheCount());
306305
if (m_data.objTypeSpecFldInfoArray == nullptr)
307306
{
308307
return nullptr;
309308
}
309+
AssertOrFailFast(index < m_data.objTypeSpecFldInfoCount);
310310

311311
return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.objTypeSpecFldInfoArray[index]);
312312
}

lib/Backend/GlobOpt.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,11 +2748,14 @@ GlobOpt::OptTagChecks(IR::Instr *instr)
27482748
ChangeValueType(nullptr, value, valueType.SetCanBeTaggedValue(false), true /*preserveSubClassInfo*/);
27492749
return false;
27502750
}
2751-
if (this->byteCodeUses)
2751+
if (!this->IsLoopPrePass())
27522752
{
2753-
this->InsertByteCodeUses(instr);
2753+
if (this->byteCodeUses)
2754+
{
2755+
this->InsertByteCodeUses(instr);
2756+
}
2757+
this->currentBlock->RemoveInstr(instr);
27542758
}
2755-
this->currentBlock->RemoveInstr(instr);
27562759
return true;
27572760
}
27582761

@@ -5435,7 +5438,8 @@ GlobOpt::GetPrepassValueTypeForDst(
54355438
IR::Instr *const instr,
54365439
Value *const src1Value,
54375440
Value *const src2Value,
5438-
bool const isValueInfoPrecise) const
5441+
bool const isValueInfoPrecise,
5442+
bool const isSafeToTransferInPrepass) const
54395443
{
54405444
// Values with definite types can be created in the loop prepass only when it is guaranteed that the value type will be the
54415445
// same on any iteration of the loop. The heuristics currently used are:
@@ -5452,13 +5456,13 @@ GlobOpt::GetPrepassValueTypeForDst(
54525456
Assert(IsLoopPrePass());
54535457
Assert(instr);
54545458

5455-
if(!desiredValueType.IsDefinite())
5456-
{
5457-
return desiredValueType;
5458-
}
5459-
54605459
if(!isValueInfoPrecise)
54615460
{
5461+
if(!desiredValueType.IsDefinite())
5462+
{
5463+
return isSafeToTransferInPrepass ? desiredValueType : desiredValueType.SetCanBeTaggedValue(true);
5464+
}
5465+
54625466
// If the desired value type is not precise, the value type of the destination is derived from the value types of the
54635467
// sources. Since the value type of a source sym is not definite, the destination value type also cannot be definite.
54645468
if(desiredValueType.IsInt() && OpCodeAttr::IsInt32(instr->m_opcode))
@@ -5471,6 +5475,7 @@ GlobOpt::GetPrepassValueTypeForDst(
54715475
// The op always produces a number, but not always an int
54725476
return desiredValueType.ToDefiniteAnyNumber();
54735477
}
5478+
// Note: ToLikely() also sets CanBeTaggedValue
54745479
return desiredValueType.ToLikely();
54755480
}
54765481

@@ -5747,7 +5752,7 @@ GlobOpt::ValueNumberTransferDstInPrepass(IR::Instr *const instr, Value *const sr
57475752
bool isSafeToTransferInPrepass = false;
57485753
isValueInfoPrecise = IsPrepassSrcValueInfoPrecise(instr, src1Val, nullptr, &isSafeToTransferInPrepass);
57495754

5750-
const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise));
5755+
const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise, isSafeToTransferInPrepass));
57515756
if(isValueInfoPrecise || isSafeToTransferInPrepass)
57525757
{
57535758
Assert(valueType == src1ValueInfo->Type());

lib/Backend/GlobOpt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ class GlobOpt
561561
bool AreFromSameBytecodeFunc(IR::RegOpnd const* src1, IR::RegOpnd const* dst) const;
562562
Value * ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val);
563563
Value * ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal);
564-
ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false) const;
564+
ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false, bool const isSafeToTransferInPrepass = false) const;
565565
bool IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue, bool * canTransferValueNumberToDst = nullptr) const;
566566
bool IsPrepassSrcValueInfoPrecise(IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool * canTransferValueNumberToDst = nullptr) const;
567567
bool IsSafeToTransferInPrepass(StackSym * const sym, ValueInfo *const srcValueInfo) const;

lib/Backend/GlobOptFields.cpp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
237237
this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
238238
SetAnyPropertyMayBeWrittenTo();
239239
}
240+
else if (inGlobOpt && indexOpnd && !indexOpnd->GetValueType().IsInt() && !currentBlock->globOptData.IsInt32TypeSpecialized(indexOpnd->m_sym))
241+
{
242+
// Write/delete to a non-integer numeric index can't alias a name on the RHS of a dot, but it change object layout
243+
this->KillAllObjectTypes(bv);
244+
}
240245
}
241246

242247
void
@@ -406,7 +411,8 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
406411
KillLiveFields(this->lengthEquivBv, bv);
407412
if (inGlobOpt)
408413
{
409-
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
414+
// Deleting an item, or pushing a property to a non-array, may change object layout
415+
KillAllObjectTypes(bv);
410416
}
411417
break;
412418

@@ -423,27 +429,32 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
423429
case Js::OpCode::CallDirect:
424430
fnHelper = instr->GetSrc1()->AsHelperCallOpnd()->m_fnHelper;
425431

426-
// Kill length field for built-ins that can update it.
427-
if(fnHelper == IR::JnHelperMethod::HelperArray_Shift
428-
|| fnHelper == IR::JnHelperMethod::HelperArray_Splice
429-
|| fnHelper == IR::JnHelperMethod::HelperArray_Unshift)
432+
switch (fnHelper)
430433
{
431-
if (nullptr != this->lengthEquivBv)
432-
{
433-
KillLiveFields(this->lengthEquivBv, bv);
434-
}
435-
if (inGlobOpt)
436-
{
437-
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
438-
}
439-
}
434+
case IR::JnHelperMethod::HelperArray_Shift:
435+
case IR::JnHelperMethod::HelperArray_Splice:
436+
case IR::JnHelperMethod::HelperArray_Unshift:
437+
// Kill length field for built-ins that can update it.
438+
if (nullptr != this->lengthEquivBv)
439+
{
440+
KillLiveFields(this->lengthEquivBv, bv);
441+
}
442+
// fall through
440443

441-
if ((fnHelper == IR::JnHelperMethod::HelperRegExp_Exec)
442-
|| (fnHelper == IR::JnHelperMethod::HelperString_Match)
443-
|| (fnHelper == IR::JnHelperMethod::HelperString_Replace))
444-
{
445-
// Consider: We may not need to kill all fields here.
446-
this->KillAllFields(bv);
444+
case IR::JnHelperMethod::HelperArray_Reverse:
445+
// Deleting an item may change object layout
446+
if (inGlobOpt)
447+
{
448+
KillAllObjectTypes(bv);
449+
}
450+
break;
451+
452+
case IR::JnHelperMethod::HelperRegExp_Exec:
453+
case IR::JnHelperMethod::HelperString_Match:
454+
case IR::JnHelperMethod::HelperString_Replace:
455+
// Consider: We may not need to kill all fields here.
456+
this->KillAllFields(bv);
457+
break;
447458
}
448459
break;
449460

lib/Backend/IRBuilder.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,8 @@ IRBuilder::Build()
774774
if (!this->RegIsTemp(dstRegSlot) && !this->RegIsConstant(dstRegSlot))
775775
{
776776
SymID symId = dstSym->m_id;
777+
778+
AssertOrFailFast(symId < m_stSlots->Length());
777779
if (this->m_stSlots->Test(symId))
778780
{
779781
// For jitted loop bodies that are in a try block, we consider any symbol that has a
@@ -4135,7 +4137,12 @@ IRBuilder::EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym)
41354137
return;
41364138
}
41374139
StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func);
4138-
if (symDst->m_isCatchObjectSym || this->m_ldSlots->TestAndSet(symId))
4140+
if (symDst->m_isCatchObjectSym)
4141+
{
4142+
return;
4143+
}
4144+
AssertOrFailFast(symId < m_ldSlots->Length());
4145+
if (this->m_ldSlots->TestAndSet(symId))
41394146
{
41404147
return;
41414148
}
@@ -4179,6 +4186,7 @@ IRBuilder::SetLoopBodyStSlot(SymID symID, bool isCatchObjectSym)
41794186
return;
41804187
}
41814188
}
4189+
AssertOrFailFast(symID < m_stSlots->Length());
41824190
this->m_stSlots->Set(symID);
41834191
}
41844192

lib/Backend/IRBuilderAsmJs.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3570,7 +3570,10 @@ IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(Js::RegSlot regSlot, IRType opndType)
35703570
void
35713571
IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(Js::RegSlot regSlot, IRType type)
35723572
{
3573-
if (GetJitLoopBodyData().GetLdSlots()->TestAndSet(regSlot))
3573+
BVFixed* ldSlotsBV = GetJitLoopBodyData().GetLdSlots();
3574+
3575+
AssertOrFailFast(regSlot < ldSlotsBV->Length());
3576+
if (ldSlotsBV->TestAndSet(regSlot))
35743577
{
35753578
return;
35763579
}
@@ -3592,7 +3595,6 @@ void
35923595
IRBuilderAsmJs::EnsureLoopBodyAsmJsStoreSlot(Js::RegSlot regSlot, IRType type)
35933596
{
35943597
Assert(!RegIsTemp(regSlot) || RegIsJitLoopYield(regSlot));
3595-
GetJitLoopBodyData().GetStSlots()->Set(regSlot);
35963598
EnsureLoopBodyAsmJsLoadSlot(regSlot, type);
35973599
}
35983600

lib/Backend/IRBuilderAsmJs.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ struct JitLoopBodyData
2626
{
2727
private:
2828
BVFixed* m_ldSlots = nullptr;
29-
BVFixed* m_stSlots = nullptr;
3029
StackSym* m_loopBodyRetIPSym = nullptr;
3130
BVFixed* m_yieldRegs = nullptr;
3231
uint32 m_loopCurRegs[WAsmJs::LIMIT];
@@ -36,7 +35,6 @@ struct JitLoopBodyData
3635
{
3736
Assert(ldSlots && stSlots && loopBodyRetIPSym);
3837
m_ldSlots = ldSlots;
39-
m_stSlots = stSlots;
4038
m_loopBodyRetIPSym = loopBodyRetIPSym;
4139
}
4240
// Use m_yieldRegs initialization to determine if m_loopCurRegs is initialized
@@ -57,14 +55,19 @@ struct JitLoopBodyData
5755
}
5856
bool IsYieldReg(Js::RegSlot reg) const
5957
{
60-
return m_yieldRegs && m_yieldRegs->Test(reg);
58+
if (!m_yieldRegs)
59+
{
60+
return false;
61+
}
62+
AssertOrFailFast(reg < m_yieldRegs->Length());
63+
return m_yieldRegs->Test(reg);
6164
}
6265
void SetRegIsYield(Js::RegSlot reg)
6366
{
6467
Assert(m_yieldRegs);
68+
AssertOrFailFast(reg < m_yieldRegs->Length());
6569
m_yieldRegs->Set(reg);
6670
}
67-
BVFixed* GetStSlots() const { return m_stSlots; }
6871
BVFixed* GetLdSlots() const { return m_ldSlots; }
6972
StackSym* GetLoopBodyRetIPSym() const { return m_loopBodyRetIPSym; }
7073

0 commit comments

Comments
 (0)