Skip to content

Commit b43772c

Browse files
committed
[1.11>master] [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 c95f834 + 0f7e500 commit b43772c

22 files changed

+216
-139
lines changed

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
@@ -1665,14 +1665,14 @@ Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, JITTimeConstructorCac
16651665

16661666
JITTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
16671667
{
1668-
Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
1668+
AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
16691669
Assert(this->constructorCaches != nullptr);
16701670
return this->constructorCaches[profiledCallSiteId];
16711671
}
16721672

16731673
void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, JITTimeConstructorCache* constructorCache)
16741674
{
1675-
Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
1675+
AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
16761676
Assert(constructorCache != nullptr);
16771677
Assert(this->constructorCaches != nullptr);
16781678
Assert(this->constructorCaches[profiledCallSiteId] == nullptr);

lib/Backend/FunctionJITTimeInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,11 +327,11 @@ FunctionJITTimeInfo::GetRuntimeInfo() const
327327
ObjTypeSpecFldInfo *
328328
FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
329329
{
330-
AssertOrFailFast(index < GetBody()->GetInlineCacheCount());
331330
if (m_data.objTypeSpecFldInfoArray == nullptr)
332331
{
333332
return nullptr;
334333
}
334+
AssertOrFailFast(index < m_data.objTypeSpecFldInfoCount);
335335

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

lib/Backend/GlobOpt.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,11 +2770,14 @@ GlobOpt::OptTagChecks(IR::Instr *instr)
27702770
ChangeValueType(nullptr, value, valueType.SetCanBeTaggedValue(false), true /*preserveSubClassInfo*/);
27712771
return false;
27722772
}
2773-
if (this->byteCodeUses)
2773+
if (!this->IsLoopPrePass())
27742774
{
2775-
this->InsertByteCodeUses(instr);
2775+
if (this->byteCodeUses)
2776+
{
2777+
this->InsertByteCodeUses(instr);
2778+
}
2779+
this->currentBlock->RemoveInstr(instr);
27762780
}
2777-
this->currentBlock->RemoveInstr(instr);
27782781
return true;
27792782
}
27802783

@@ -5469,7 +5472,8 @@ GlobOpt::GetPrepassValueTypeForDst(
54695472
IR::Instr *const instr,
54705473
Value *const src1Value,
54715474
Value *const src2Value,
5472-
bool const isValueInfoPrecise) const
5475+
bool const isValueInfoPrecise,
5476+
bool const isSafeToTransferInPrepass) const
54735477
{
54745478
// Values with definite types can be created in the loop prepass only when it is guaranteed that the value type will be the
54755479
// same on any iteration of the loop. The heuristics currently used are:
@@ -5486,13 +5490,13 @@ GlobOpt::GetPrepassValueTypeForDst(
54865490
Assert(IsLoopPrePass());
54875491
Assert(instr);
54885492

5489-
if(!desiredValueType.IsDefinite())
5490-
{
5491-
return desiredValueType;
5492-
}
5493-
54945493
if(!isValueInfoPrecise)
54955494
{
5495+
if(!desiredValueType.IsDefinite())
5496+
{
5497+
return isSafeToTransferInPrepass ? desiredValueType : desiredValueType.SetCanBeTaggedValue(true);
5498+
}
5499+
54965500
// If the desired value type is not precise, the value type of the destination is derived from the value types of the
54975501
// sources. Since the value type of a source sym is not definite, the destination value type also cannot be definite.
54985502
if(desiredValueType.IsInt() && OpCodeAttr::IsInt32(instr->m_opcode))
@@ -5505,6 +5509,7 @@ GlobOpt::GetPrepassValueTypeForDst(
55055509
// The op always produces a number, but not always an int
55065510
return desiredValueType.ToDefiniteAnyNumber();
55075511
}
5512+
// Note: ToLikely() also sets CanBeTaggedValue
55085513
return desiredValueType.ToLikely();
55095514
}
55105515

@@ -5781,7 +5786,7 @@ GlobOpt::ValueNumberTransferDstInPrepass(IR::Instr *const instr, Value *const sr
57815786
bool isSafeToTransferInPrepass = false;
57825787
isValueInfoPrecise = IsPrepassSrcValueInfoPrecise(instr, src1Val, nullptr, &isSafeToTransferInPrepass);
57835788

5784-
const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise));
5789+
const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise, isSafeToTransferInPrepass));
57855790
if(isValueInfoPrecise || isSafeToTransferInPrepass)
57865791
{
57875792
Assert(valueType == src1ValueInfo->Type());

lib/Backend/GlobOpt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ class GlobOpt
559559
bool AreFromSameBytecodeFunc(IR::RegOpnd const* src1, IR::RegOpnd const* dst) const;
560560
Value * ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val);
561561
Value * ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal);
562-
ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false) const;
562+
ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false, bool const isSafeToTransferInPrepass = false) const;
563563
bool IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue, bool * canTransferValueNumberToDst = nullptr) const;
564564
bool IsPrepassSrcValueInfoPrecise(IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool * canTransferValueNumberToDst = nullptr) const;
565565
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
@@ -228,6 +228,11 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
228228
this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
229229
SetAnyPropertyMayBeWrittenTo();
230230
}
231+
else if (inGlobOpt && indexOpnd && !indexOpnd->GetValueType().IsInt() && !currentBlock->globOptData.IsInt32TypeSpecialized(indexOpnd->m_sym))
232+
{
233+
// Write/delete to a non-integer numeric index can't alias a name on the RHS of a dot, but it change object layout
234+
this->KillAllObjectTypes(bv);
235+
}
231236
}
232237

233238
void
@@ -397,7 +402,8 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
397402
KillLiveFields(this->lengthEquivBv, bv);
398403
if (inGlobOpt)
399404
{
400-
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
405+
// Deleting an item, or pushing a property to a non-array, may change object layout
406+
KillAllObjectTypes(bv);
401407
}
402408
break;
403409

@@ -414,27 +420,32 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
414420
case Js::OpCode::CallDirect:
415421
fnHelper = instr->GetSrc1()->AsHelperCallOpnd()->m_fnHelper;
416422

417-
// Kill length field for built-ins that can update it.
418-
if(fnHelper == IR::JnHelperMethod::HelperArray_Shift
419-
|| fnHelper == IR::JnHelperMethod::HelperArray_Splice
420-
|| fnHelper == IR::JnHelperMethod::HelperArray_Unshift)
423+
switch (fnHelper)
421424
{
422-
if (nullptr != this->lengthEquivBv)
423-
{
424-
KillLiveFields(this->lengthEquivBv, bv);
425-
}
426-
if (inGlobOpt)
427-
{
428-
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
429-
}
430-
}
425+
case IR::JnHelperMethod::HelperArray_Shift:
426+
case IR::JnHelperMethod::HelperArray_Splice:
427+
case IR::JnHelperMethod::HelperArray_Unshift:
428+
// Kill length field for built-ins that can update it.
429+
if (nullptr != this->lengthEquivBv)
430+
{
431+
KillLiveFields(this->lengthEquivBv, bv);
432+
}
433+
// fall through
431434

432-
if ((fnHelper == IR::JnHelperMethod::HelperRegExp_Exec)
433-
|| (fnHelper == IR::JnHelperMethod::HelperString_Match)
434-
|| (fnHelper == IR::JnHelperMethod::HelperString_Replace))
435-
{
436-
// Consider: We may not need to kill all fields here.
437-
this->KillAllFields(bv);
435+
case IR::JnHelperMethod::HelperArray_Reverse:
436+
// Deleting an item may change object layout
437+
if (inGlobOpt)
438+
{
439+
KillAllObjectTypes(bv);
440+
}
441+
break;
442+
443+
case IR::JnHelperMethod::HelperRegExp_Exec:
444+
case IR::JnHelperMethod::HelperString_Match:
445+
case IR::JnHelperMethod::HelperString_Replace:
446+
// Consider: We may not need to kill all fields here.
447+
this->KillAllFields(bv);
448+
break;
438449
}
439450
break;
440451

lib/Backend/IRBuilder.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,8 @@ IRBuilder::Build()
724724
if (!this->RegIsTemp(dstRegSlot) && !this->RegIsConstant(dstRegSlot))
725725
{
726726
SymID symId = dstSym->m_id;
727+
728+
AssertOrFailFast(symId < m_stSlots->Length());
727729
if (this->m_stSlots->Test(symId))
728730
{
729731
// For jitted loop bodies that are in a try block, we consider any symbol that has a
@@ -4076,7 +4078,12 @@ IRBuilder::EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym)
40764078
return;
40774079
}
40784080
StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func);
4079-
if (symDst->m_isCatchObjectSym || this->m_ldSlots->TestAndSet(symId))
4081+
if (symDst->m_isCatchObjectSym)
4082+
{
4083+
return;
4084+
}
4085+
AssertOrFailFast(symId < m_ldSlots->Length());
4086+
if (this->m_ldSlots->TestAndSet(symId))
40804087
{
40814088
return;
40824089
}
@@ -4120,6 +4127,7 @@ IRBuilder::SetLoopBodyStSlot(SymID symID, bool isCatchObjectSym)
41204127
return;
41214128
}
41224129
}
4130+
AssertOrFailFast(symID < m_stSlots->Length());
41234131
this->m_stSlots->Set(symID);
41244132
}
41254133

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

lib/Backend/NativeEntryPointData.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,20 +321,14 @@ NativeEntryPointData::CleanupXDataInfo()
321321
{
322322
if (this->xdataInfo != nullptr)
323323
{
324+
XDataAllocator::Unregister(this->xdataInfo);
324325
#ifdef _WIN32
325326
if (this->xdataInfo->functionTable
326-
&& !DelayDeletingFunctionTable::AddEntry(this->xdataInfo->functionTable))
327+
&& !DelayDeletingFunctionTable::AddEntry(this->xdataInfo))
327328
{
328-
DelayDeletingFunctionTable::DeleteFunctionTable(this->xdataInfo->functionTable);
329+
DelayDeletingFunctionTable::DeleteFunctionTable(this->xdataInfo);
329330
}
330331
#endif
331-
XDataAllocator::Unregister(this->xdataInfo);
332-
#if defined(_M_ARM)
333-
if (JITManager::GetJITManager()->IsOOPJITEnabled())
334-
#endif
335-
{
336-
HeapDelete(this->xdataInfo);
337-
}
338332
this->xdataInfo = nullptr;
339333
}
340334
}

0 commit comments

Comments
 (0)