Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

February 2019 Security Update #5936

Merged
merged 13 commits into from
Feb 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Build/NuGet/.pack-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.11.5
1.11.6
14 changes: 1 addition & 13 deletions lib/Backend/CodeGenWorkItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,19 +210,7 @@ void CodeGenWorkItem::OnWorkItemProcessFail(NativeCodeGenerator* codeGen)
#if PDATA_ENABLED & defined(_WIN32)
if (this->entryPointInfo)
{
XDataAllocation * xdataAllocation = this->entryPointInfo->GetNativeEntryPointData()->GetXDataInfo();
if (xdataAllocation)
{
void* functionTable = xdataAllocation->functionTable;
if (functionTable)
{
if (!DelayDeletingFunctionTable::AddEntry(functionTable))
{
PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("[%d]OnWorkItemProcessFail: Failed to add to slist, table: %llx\n"), GetCurrentThreadId(), functionTable);
DelayDeletingFunctionTable::DeleteFunctionTable(functionTable);
}
}
}
this->entryPointInfo->GetNativeEntryPointData()->CleanupXDataInfo();
}
#endif
codeGen->FreeNativeCodeGenAllocation(this->allocation->allocation->address);
Expand Down
4 changes: 2 additions & 2 deletions lib/Backend/Func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1673,14 +1673,14 @@ Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, JITTimeConstructorCac

JITTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
{
Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
Assert(this->constructorCaches != nullptr);
return this->constructorCaches[profiledCallSiteId];
}

void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, JITTimeConstructorCache* constructorCache)
{
Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
Assert(constructorCache != nullptr);
Assert(this->constructorCaches != nullptr);
Assert(this->constructorCaches[profiledCallSiteId] == nullptr);
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/FunctionJITTimeInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,11 @@ FunctionJITTimeInfo::GetRuntimeInfo() const
ObjTypeSpecFldInfo *
FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
{
AssertOrFailFast(index < GetBody()->GetInlineCacheCount());
if (m_data.objTypeSpecFldInfoArray == nullptr)
{
return nullptr;
}
AssertOrFailFast(index < m_data.objTypeSpecFldInfoCount);

return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.objTypeSpecFldInfoArray[index]);
}
Expand Down
25 changes: 15 additions & 10 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2748,11 +2748,14 @@ GlobOpt::OptTagChecks(IR::Instr *instr)
ChangeValueType(nullptr, value, valueType.SetCanBeTaggedValue(false), true /*preserveSubClassInfo*/);
return false;
}
if (this->byteCodeUses)
if (!this->IsLoopPrePass())
{
this->InsertByteCodeUses(instr);
if (this->byteCodeUses)
{
this->InsertByteCodeUses(instr);
}
this->currentBlock->RemoveInstr(instr);
}
this->currentBlock->RemoveInstr(instr);
return true;
}

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

if(!desiredValueType.IsDefinite())
{
return desiredValueType;
}

if(!isValueInfoPrecise)
{
if(!desiredValueType.IsDefinite())
{
return isSafeToTransferInPrepass ? desiredValueType : desiredValueType.SetCanBeTaggedValue(true);
}

// If the desired value type is not precise, the value type of the destination is derived from the value types of the
// sources. Since the value type of a source sym is not definite, the destination value type also cannot be definite.
if(desiredValueType.IsInt() && OpCodeAttr::IsInt32(instr->m_opcode))
Expand All @@ -5471,6 +5475,7 @@ GlobOpt::GetPrepassValueTypeForDst(
// The op always produces a number, but not always an int
return desiredValueType.ToDefiniteAnyNumber();
}
// Note: ToLikely() also sets CanBeTaggedValue
return desiredValueType.ToLikely();
}

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

const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise));
const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise, isSafeToTransferInPrepass));
if(isValueInfoPrecise || isSafeToTransferInPrepass)
{
Assert(valueType == src1ValueInfo->Type());
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/GlobOpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ class GlobOpt
bool AreFromSameBytecodeFunc(IR::RegOpnd const* src1, IR::RegOpnd const* dst) const;
Value * ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val);
Value * ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal);
ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false) const;
ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false, bool const isSafeToTransferInPrepass = false) const;
bool IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue, bool * canTransferValueNumberToDst = nullptr) const;
bool IsPrepassSrcValueInfoPrecise(IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool * canTransferValueNumberToDst = nullptr) const;
bool IsSafeToTransferInPrepass(StackSym * const sym, ValueInfo *const srcValueInfo) const;
Expand Down
51 changes: 31 additions & 20 deletions lib/Backend/GlobOptFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
SetAnyPropertyMayBeWrittenTo();
}
else if (inGlobOpt && indexOpnd && !indexOpnd->GetValueType().IsInt() && !currentBlock->globOptData.IsInt32TypeSpecialized(indexOpnd->m_sym))
{
// Write/delete to a non-integer numeric index can't alias a name on the RHS of a dot, but it change object layout
this->KillAllObjectTypes(bv);
}
}

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

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

// Kill length field for built-ins that can update it.
if(fnHelper == IR::JnHelperMethod::HelperArray_Shift
|| fnHelper == IR::JnHelperMethod::HelperArray_Splice
|| fnHelper == IR::JnHelperMethod::HelperArray_Unshift)
switch (fnHelper)
{
if (nullptr != this->lengthEquivBv)
{
KillLiveFields(this->lengthEquivBv, bv);
}
if (inGlobOpt)
{
KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
}
}
case IR::JnHelperMethod::HelperArray_Shift:
case IR::JnHelperMethod::HelperArray_Splice:
case IR::JnHelperMethod::HelperArray_Unshift:
// Kill length field for built-ins that can update it.
if (nullptr != this->lengthEquivBv)
{
KillLiveFields(this->lengthEquivBv, bv);
}
// fall through

if ((fnHelper == IR::JnHelperMethod::HelperRegExp_Exec)
|| (fnHelper == IR::JnHelperMethod::HelperString_Match)
|| (fnHelper == IR::JnHelperMethod::HelperString_Replace))
{
// Consider: We may not need to kill all fields here.
this->KillAllFields(bv);
case IR::JnHelperMethod::HelperArray_Reverse:
// Deleting an item may change object layout
if (inGlobOpt)
{
KillAllObjectTypes(bv);
}
break;

case IR::JnHelperMethod::HelperRegExp_Exec:
case IR::JnHelperMethod::HelperString_Match:
case IR::JnHelperMethod::HelperString_Replace:
// Consider: We may not need to kill all fields here.
this->KillAllFields(bv);
break;
}
break;

Expand Down
10 changes: 9 additions & 1 deletion lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,8 @@ IRBuilder::Build()
if (!this->RegIsTemp(dstRegSlot) && !this->RegIsConstant(dstRegSlot))
{
SymID symId = dstSym->m_id;

AssertOrFailFast(symId < m_stSlots->Length());
if (this->m_stSlots->Test(symId))
{
// For jitted loop bodies that are in a try block, we consider any symbol that has a
Expand Down Expand Up @@ -4135,7 +4137,12 @@ IRBuilder::EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym)
return;
}
StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func);
if (symDst->m_isCatchObjectSym || this->m_ldSlots->TestAndSet(symId))
if (symDst->m_isCatchObjectSym)
{
return;
}
AssertOrFailFast(symId < m_ldSlots->Length());
if (this->m_ldSlots->TestAndSet(symId))
{
return;
}
Expand Down Expand Up @@ -4179,6 +4186,7 @@ IRBuilder::SetLoopBodyStSlot(SymID symID, bool isCatchObjectSym)
return;
}
}
AssertOrFailFast(symID < m_stSlots->Length());
this->m_stSlots->Set(symID);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/Backend/IRBuilderAsmJs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3570,7 +3570,10 @@ IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(Js::RegSlot regSlot, IRType opndType)
void
IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(Js::RegSlot regSlot, IRType type)
{
if (GetJitLoopBodyData().GetLdSlots()->TestAndSet(regSlot))
BVFixed* ldSlotsBV = GetJitLoopBodyData().GetLdSlots();

AssertOrFailFast(regSlot < ldSlotsBV->Length());
if (ldSlotsBV->TestAndSet(regSlot))
{
return;
}
Expand All @@ -3592,7 +3595,6 @@ void
IRBuilderAsmJs::EnsureLoopBodyAsmJsStoreSlot(Js::RegSlot regSlot, IRType type)
{
Assert(!RegIsTemp(regSlot) || RegIsJitLoopYield(regSlot));
GetJitLoopBodyData().GetStSlots()->Set(regSlot);
EnsureLoopBodyAsmJsLoadSlot(regSlot, type);
}

Expand Down
11 changes: 7 additions & 4 deletions lib/Backend/IRBuilderAsmJs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct JitLoopBodyData
{
private:
BVFixed* m_ldSlots = nullptr;
BVFixed* m_stSlots = nullptr;
StackSym* m_loopBodyRetIPSym = nullptr;
BVFixed* m_yieldRegs = nullptr;
uint32 m_loopCurRegs[WAsmJs::LIMIT];
Expand All @@ -36,7 +35,6 @@ struct JitLoopBodyData
{
Assert(ldSlots && stSlots && loopBodyRetIPSym);
m_ldSlots = ldSlots;
m_stSlots = stSlots;
m_loopBodyRetIPSym = loopBodyRetIPSym;
}
// Use m_yieldRegs initialization to determine if m_loopCurRegs is initialized
Expand All @@ -57,14 +55,19 @@ struct JitLoopBodyData
}
bool IsYieldReg(Js::RegSlot reg) const
{
return m_yieldRegs && m_yieldRegs->Test(reg);
if (!m_yieldRegs)
{
return false;
}
AssertOrFailFast(reg < m_yieldRegs->Length());
return m_yieldRegs->Test(reg);
}
void SetRegIsYield(Js::RegSlot reg)
{
Assert(m_yieldRegs);
AssertOrFailFast(reg < m_yieldRegs->Length());
m_yieldRegs->Set(reg);
}
BVFixed* GetStSlots() const { return m_stSlots; }
BVFixed* GetLdSlots() const { return m_ldSlots; }
StackSym* GetLoopBodyRetIPSym() const { return m_loopBodyRetIPSym; }

Expand Down
12 changes: 3 additions & 9 deletions lib/Backend/NativeEntryPointData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,20 +321,14 @@ NativeEntryPointData::CleanupXDataInfo()
{
if (this->xdataInfo != nullptr)
{
XDataAllocator::Unregister(this->xdataInfo);
#ifdef _WIN32
if (this->xdataInfo->functionTable
&& !DelayDeletingFunctionTable::AddEntry(this->xdataInfo->functionTable))
&& !DelayDeletingFunctionTable::AddEntry(this->xdataInfo))
{
DelayDeletingFunctionTable::DeleteFunctionTable(this->xdataInfo->functionTable);
DelayDeletingFunctionTable::DeleteFunctionTable(this->xdataInfo);
}
#endif
XDataAllocator::Unregister(this->xdataInfo);
#if defined(_M_ARM)
if (JITManager::GetJITManager()->IsOOPJITEnabled())
#endif
{
HeapDelete(this->xdataInfo);
}
this->xdataInfo = nullptr;
}
}
Expand Down
6 changes: 2 additions & 4 deletions lib/Backend/NativeEntryPointData.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,15 @@ class NativeEntryPointData

#if PDATA_ENABLED
XDataAllocation* GetXDataInfo() { return this->xdataInfo; }
void SetXDataInfo(XDataAllocation* xdataInfo) { this->xdataInfo = xdataInfo; }
void CleanupXDataInfo();
void SetXDataInfo(XDataAllocation* xdataInfo) { this->xdataInfo = xdataInfo; }
#endif
private:
void RegisterEquivalentTypeCaches(Js::ScriptContext * scriptContext, Js::EntryPointInfo * entryPointInfo);
void UnregisterEquivalentTypeCaches(Js::ScriptContext * scriptContext);
void FreePropertyGuards();

void FreeNativeCode(Js::ScriptContext * scriptContext, bool isShutdown);
#if PDATA_ENABLED
void CleanupXDataInfo();
#endif

FieldNoBarrier(Js::JavascriptMethod) nativeAddress;
FieldNoBarrier(Js::JavascriptMethod) thunkAddress;
Expand Down
3 changes: 1 addition & 2 deletions lib/Backend/PDataManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ void PDataManager::UnregisterPdata(RUNTIME_FUNCTION* pdata)
{
if (AutoSystemInfo::Data.IsWin8OrLater())
{
// TODO: need to move to background?
DelayDeletingFunctionTable::DeleteFunctionTable(pdata);
NtdllLibrary::Instance->DeleteGrowableFunctionTable(pdata);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Common/ChakraCoreVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// ChakraCore version number definitions (used in ChakraCore binary metadata)
#define CHAKRA_CORE_MAJOR_VERSION 1
#define CHAKRA_CORE_MINOR_VERSION 11
#define CHAKRA_CORE_PATCH_VERSION 5
#define CHAKRA_CORE_PATCH_VERSION 6
#define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0.

// -------------
Expand Down
2 changes: 2 additions & 0 deletions lib/Common/Memory/Chakra.Common.Memory.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<ClCompile>
<AdditionalIncludeDirectories>
$(MSBuildThisFileDirectory);
$(MSBuildThisFileDirectory)..\..\JITClient;
$(ChakraJITIDLIntDir);
$(MSBuildThisFileDirectory)..;
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
Expand Down
Loading