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

ChakraCore 2018-02 security updates #4676

Merged
merged 14 commits into from
Feb 13, 2018
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
3 changes: 3 additions & 0 deletions lib/Backend/FlowGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,15 @@ FlowGraph::Build(void)
case Js::OpCode::TryCatch:
if (this->catchLabelStack)
{
AssertOrFailFast(!this->catchLabelStack->Empty());
this->catchLabelStack->Pop();
}
break;

case Js::OpCode::TryFinally:
if (this->finallyLabelStack)
{
AssertOrFailFast(!this->finallyLabelStack->Empty());
this->finallyLabelStack->Pop();
}
break;
Expand Down Expand Up @@ -497,6 +499,7 @@ FlowGraph::Build(void)
}
else if (instr->m_opcode == Js::OpCode::Finally)
{
AssertOrFailFast(!this->finallyLabelStack->Empty());
this->finallyLabelStack->Pop();
}
}
Expand Down
13 changes: 6 additions & 7 deletions lib/Backend/FunctionJITTimeInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ FunctionJITTimeInfo::BuildJITTimeData(
if(objTypeSpecInfo)
{
jitData->objTypeSpecFldInfoCount = jitData->bodyData->inlineCacheCount;
jitData->objTypeSpecFldInfoArray = (ObjTypeSpecFldIDL**)objTypeSpecInfo;
jitData->objTypeSpecFldInfoArray = unsafe_write_barrier_cast<ObjTypeSpecFldIDL**>(objTypeSpecInfo);
}
for (Js::InlineCacheIndex i = 0; i < jitData->bodyData->inlineCacheCount; ++i)
{
Expand All @@ -131,7 +131,7 @@ FunctionJITTimeInfo::BuildJITTimeData(
Assert(globObjTypeSpecInfo != nullptr);

jitData->globalObjTypeSpecFldInfoCount = codeGenData->GetGlobalObjTypeSpecFldInfoCount();
jitData->globalObjTypeSpecFldInfoArray = (ObjTypeSpecFldIDL**)globObjTypeSpecInfo;
jitData->globalObjTypeSpecFldInfoArray = unsafe_write_barrier_cast<ObjTypeSpecFldIDL**>(globObjTypeSpecInfo);
}
const Js::FunctionCodeGenJitTimeData * nextJITData = codeGenData->GetNext();
if (nextJITData != nullptr)
Expand Down Expand Up @@ -259,7 +259,7 @@ FunctionJITTimeInfo::GetRuntimeInfo() const
ObjTypeSpecFldInfo *
FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
{
Assert(index < GetBody()->GetInlineCacheCount());
AssertOrFailFast(index < GetBody()->GetInlineCacheCount());
if (m_data.objTypeSpecFldInfoArray == nullptr)
{
return nullptr;
Expand All @@ -271,7 +271,7 @@ FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
ObjTypeSpecFldInfo *
FunctionJITTimeInfo::GetGlobalObjTypeSpecFldInfo(uint index) const
{
Assert(index < m_data.globalObjTypeSpecFldInfoCount);
AssertOrFailFast(index < m_data.globalObjTypeSpecFldInfoCount);

return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.globalObjTypeSpecFldInfoArray[index]);
}
Expand All @@ -298,8 +298,7 @@ FunctionJITTimeInfo::GetLdFldInlinee(Js::InlineCacheIndex inlineCacheIndex) cons
{
return nullptr;
}
Assert(inlineCacheIndex < m_data.ldFldInlineeCount);

AssertOrFailFast(inlineCacheIndex < m_data.ldFldInlineeCount);

return reinterpret_cast<const FunctionJITTimeInfo*>(m_data.ldFldInlinees[inlineCacheIndex]);
}
Expand All @@ -312,7 +311,7 @@ FunctionJITTimeInfo::GetInlinee(Js::ProfileId profileId) const
{
return nullptr;
}
Assert(profileId < m_data.inlineeCount);
AssertOrFailFast(profileId < m_data.inlineeCount);

auto inlinee = reinterpret_cast<const FunctionJITTimeInfo *>(m_data.inlinees[profileId]);
if (inlinee == nullptr && m_data.inlineesRecursionFlags[profileId])
Expand Down
43 changes: 42 additions & 1 deletion lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5191,7 +5191,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
if (!PHASE_OFF(Js::OptTagChecksPhase, this->func) &&
(src1ValueInfo == nullptr || src1ValueInfo->IsUninitialized()))
{
return this->NewGenericValue(ValueType::GetObject(ObjectType::Object), dst);
return this->NewGenericValue(ValueType::GetObject(ObjectType::Object).ToLikely().SetCanBeTaggedValue(false), dst);
}
break;

Expand Down Expand Up @@ -15399,6 +15399,47 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
}
break;
}

case Js::OpCode::InitProto:
{
// Find the 'this' parameter and check if it's possible for it to be an array
IR::Opnd *const arrayOpnd = instr->GetSrc1();
Assert(arrayOpnd);
const ValueType arrayValueType(arrayOpnd->GetValueType());
if(!arrayOpnd->IsRegOpnd() || (useValueTypes && arrayValueType.IsNotArrayOrObjectWithArray()))
{
break;
}

if(doNativeArrayTypeSpec && !(useValueTypes && arrayValueType.IsNotNativeArray()))
{
kills.SetKillsNativeArrays();
}
break;
}

case Js::OpCode::InitClass:
Assert(instr->GetSrc1());
if (instr->GetSrc2() == nullptr)
{
// No extends operand, so the InitClass will not make something into a prototype
break;
}

if(doNativeArrayTypeSpec)
{
// Class/object construction can make something a prototype
kills.SetKillsNativeArrays();
}
break;

case Js::OpCode::NewScObjectNoCtor:
if(doNativeArrayTypeSpec)
{
// Class/object construction can make something a prototype
kills.SetKillsNativeArrays();
}
break;
}

return kills;
Expand Down
56 changes: 32 additions & 24 deletions lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,7 @@ IRBuilder::Build()
this->m_loopBodyLocalsStartSlot = (Js::PropertyId)(localsOffset / sizeof(Js::Var));
}

#if DBG
m_offsetToInstructionCount = offsetToInstructionCount;
#endif
m_offsetToInstruction = JitAnewArrayZ(m_tempAlloc, IR::Instr *, offsetToInstructionCount);

#ifdef BYTECODE_BRANCH_ISLAND
Expand Down Expand Up @@ -820,7 +818,8 @@ IRBuilder::Build()
m_lastInstr->m_opcode == Js::OpCode::RuntimeTypeError)
{
uint32 lastInstrOffset = m_lastInstr->GetByteCodeOffset();
Assert(lastInstrOffset < m_offsetToInstructionCount);

AssertOrFailFast(lastInstrOffset < m_offsetToInstructionCount);
#if DBG
__analysis_assume(lastInstrOffset < this->m_offsetToInstructionCount);
#endif
Expand Down Expand Up @@ -1069,7 +1068,7 @@ IRBuilder::CreateLabel(IR::BranchInstr * branchInstr, uint& offset)

for (;;)
{
Assert(offset < m_offsetToInstructionCount);
AssertOrFailFast(offset < m_offsetToInstructionCount);
targetInstr = this->m_offsetToInstruction[offset];
if (targetInstr != nullptr)
{
Expand Down Expand Up @@ -1118,7 +1117,7 @@ IRBuilder::CreateLabel(IR::BranchInstr * branchInstr, uint& offset)

void IRBuilder::InsertInstr(IR::Instr *instr, IR::Instr* insertBeforeInstr)
{
Assert(insertBeforeInstr->GetByteCodeOffset() < m_offsetToInstructionCount);
AssertOrFailFast(insertBeforeInstr->GetByteCodeOffset() < m_offsetToInstructionCount);
instr->SetByteCodeOffset(insertBeforeInstr);
uint32 offset = insertBeforeInstr->GetByteCodeOffset();
if (m_offsetToInstruction[offset] == insertBeforeInstr)
Expand Down Expand Up @@ -1150,7 +1149,7 @@ IRBuilder::AddInstr(IR::Instr *instr, uint32 offset)
m_lastInstr->InsertAfter(instr);
if (offset != Js::Constants::NoByteCodeOffset)
{
Assert(offset < m_offsetToInstructionCount);
AssertOrFailFast(offset < m_offsetToInstructionCount);
if (m_offsetToInstruction[offset] == nullptr)
{
m_offsetToInstruction[offset] = instr;
Expand Down Expand Up @@ -1213,6 +1212,7 @@ IRBuilder::BuildIndirOpnd(IR::RegOpnd *baseReg, uint32 offset, const char16 *des
IR::SymOpnd *
IRBuilder::BuildFieldOpnd(Js::OpCode newOpcode, Js::RegSlot reg, Js::PropertyId propertyId, Js::PropertyIdIndexType propertyIdIndex, PropertyKind propertyKind, uint inlineCacheIndex)
{
AssertOrFailFast(inlineCacheIndex < m_func->GetJITFunctionBody()->GetInlineCacheCount() || inlineCacheIndex == Js::Constants::NoInlineCacheIndex);
PropertySym * propertySym = BuildFieldSym(reg, propertyId, propertyIdIndex, inlineCacheIndex, propertyKind);
IR::SymOpnd * symOpnd;

Expand Down Expand Up @@ -1798,7 +1798,8 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
case Js::OpCode::Catch:
if (this->handlerOffsetStack)
{
Assert(this->handlerOffsetStack->Top().Second() == true);
AssertOrFailFast(!this->handlerOffsetStack->Empty());
AssertOrFailFast(this->handlerOffsetStack->Top().Second() == true);
this->handlerOffsetStack->Pop();
}
dstIsCatchObject = true;
Expand Down Expand Up @@ -6125,19 +6126,24 @@ IRBuilder::BuildProfiledCallI(Js::OpCode opcode, uint32 offset, Js::RegSlot retu
if(this->m_func->GetWorkItem()->GetJITTimeInfo())
{
const FunctionJITTimeInfo *inlinerData = this->m_func->GetWorkItem()->GetJITTimeInfo();
if(!(this->IsLoopBody() && PHASE_OFF(Js::InlineInJitLoopBodyPhase, this->m_func)) &&
inlinerData && inlinerData->GetInlineesBV() && (!inlinerData->GetInlineesBV()->Test(profileId)
if (!(this->IsLoopBody() && PHASE_OFF(Js::InlineInJitLoopBodyPhase, this->m_func))
&& inlinerData && inlinerData->GetInlineesBV())
{
AssertOrFailFast(profileId < inlinerData->GetInlineesBV()->Length());
if (!inlinerData->GetInlineesBV()->Test(profileId)
#if DBG
|| (PHASE_STRESS(Js::BailOnNoProfilePhase, this->m_func->GetTopFunc()) &&
(CONFIG_FLAG(SkipFuncCountForBailOnNoProfile) < 0 ||
this->m_func->m_callSiteCount >= (uint)CONFIG_FLAG(SkipFuncCountForBailOnNoProfile)))
|| (PHASE_STRESS(Js::BailOnNoProfilePhase, this->m_func->GetTopFunc())
&& (CONFIG_FLAG(SkipFuncCountForBailOnNoProfile) < 0
|| this->m_func->m_callSiteCount >= (uint)CONFIG_FLAG(SkipFuncCountForBailOnNoProfile)))
#endif
))
{
this->InsertBailOnNoProfile(offset);
isProtectedByNoProfileBailout = true;
)
{
this->InsertBailOnNoProfile(offset);
isProtectedByNoProfileBailout = true;
}
}
else

if (!isProtectedByNoProfileBailout)
{
this->callTreeHasSomeProfileInfo = true;
}
Expand Down Expand Up @@ -6398,19 +6404,20 @@ IRBuilder::BuildCallCommon(IR::Instr * instr, StackSym * symDst, Js::ArgSlot arg
#endif

// Link all the args of this call by creating a def/use chain through the src2.

for (argInstr = this->m_argStack->Pop();
argInstr && argInstr->m_opcode != Js::OpCode::StartCall;
argInstr = this->m_argStack->Pop())
AssertOrFailFast(!m_argStack->Empty());
for (argInstr = m_argStack->Pop();
argInstr && !m_argStack->Empty() && argInstr->m_opcode != Js::OpCode::StartCall;
argInstr = m_argStack->Pop())
{
prevInstr->SetSrc2(argInstr->GetDst());
prevInstr = argInstr;
#if DBG
count++;
#endif
}
AssertOrFailFast(argInstr == nullptr || argInstr->m_opcode == Js::OpCode::StartCall);

if (this->m_argStack->Empty())
if (m_argStack->Empty())
{
this->callTreeHasSomeProfileInfo = false;
}
Expand Down Expand Up @@ -6736,7 +6743,8 @@ IRBuilder::BuildEmpty(Js::OpCode newOpcode, uint32 offset)
case Js::OpCode::Finally:
if (this->handlerOffsetStack)
{
Assert(this->handlerOffsetStack->Top().Second() == false);
AssertOrFailFast(!this->handlerOffsetStack->Empty());
AssertOrFailFast(this->handlerOffsetStack->Top().Second() == false);
this->handlerOffsetStack->Pop();
}
finallyBlockLevel++;
Expand Down Expand Up @@ -6971,7 +6979,6 @@ IRBuilder::BuildBr(Js::OpCode newOpcode, uint32 offset)
IR::BranchInstr * branchInstr;
const unaligned Js::OpLayoutBr *branchInsn = m_jnReader.Br();
unsigned int targetOffset = m_jnReader.GetCurrentOffset() + branchInsn->RelativeJumpOffset;

#ifdef BYTECODE_BRANCH_ISLAND
bool isLongBranchIsland = (m_jnReader.PeekOp() == Js::OpCode::BrLong);
if (isLongBranchIsland)
Expand Down Expand Up @@ -7154,6 +7161,7 @@ IRBuilder::BuildBrEnvProperty(Js::OpCode newOpcode, uint32 offset)
BranchReloc *
IRBuilder::AddBranchInstr(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
{
AssertOrFailFast(targetOffset <= m_func->GetJITFunctionBody()->GetByteCodeLength());
//
// Loop jitting would be done only till the LoopEnd
// Any branches beyond that offset are for the return stmt
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ class IRBuilder
Func * m_func;
IR::Instr * m_lastInstr;
IR::Instr ** m_offsetToInstruction;
uint32 m_offsetToInstructionCount;
uint32 m_functionStartOffset;
Js::ByteCodeReader m_jnReader;
Js::StatementReader<Js::FunctionBody::ArenaStatementMapList> m_statementReader;
Expand Down Expand Up @@ -363,7 +364,6 @@ class IRBuilder
// used to estimate how much stack we should probe for at the
// beginning of a JITted function.
#if DBG
uint32 m_offsetToInstructionCount;
uint32 m_callsOnStack;
#endif
uint32 m_argsOnStack;
Expand Down
16 changes: 8 additions & 8 deletions lib/Backend/IRBuilderAsmJs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ IRBuilderAsmJs::Build()
offsetToInstructionCount = lastOffset + 2;
}

#if DBG
m_offsetToInstructionCount = offsetToInstructionCount;
#endif
m_offsetToInstruction = JitAnewArrayZ(m_tempAlloc, IR::Instr *, offsetToInstructionCount);

LoadNativeCodeData();
Expand Down Expand Up @@ -219,7 +217,7 @@ IRBuilderAsmJs::AddInstr(IR::Instr * instr, uint32 offset)
m_lastInstr->InsertAfter(instr);
if (offset != Js::Constants::NoByteCodeOffset)
{
Assert(offset < m_offsetToInstructionCount);
AssertOrFailFast(offset < m_offsetToInstructionCount);
if (m_offsetToInstruction[offset] == nullptr)
{
m_offsetToInstruction[offset] = instr;
Expand Down Expand Up @@ -669,6 +667,7 @@ IRBuilderAsmJs::RegIsConstant(Js::RegSlot reg)
BranchReloc *
IRBuilderAsmJs::AddBranchInstr(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
{
AssertOrFailFast(targetOffset <= m_func->GetJITFunctionBody()->GetByteCodeLength());
//
// Loop jitting would be done only till the LoopEnd
// Any branches beyond that offset are for the return statement
Expand Down Expand Up @@ -1041,8 +1040,8 @@ IRBuilderAsmJs::CreateLabel(IR::BranchInstr * branchInstr, uint & offset)
IR::Instr * targetInstr = nullptr;
while (targetInstr == nullptr)
{
AssertOrFailFast(offset < m_offsetToInstructionCount);
targetInstr = m_offsetToInstruction[offset];
Assert(offset < m_offsetToInstructionCount);
++offset;
}

Expand Down Expand Up @@ -1788,7 +1787,7 @@ IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSl
instr->AsProfiledInstr()->u.profileId = profileId;
}
}

AssertOrFailFast(!this->m_argOffsetStack->Empty());
argOffset = m_argOffsetStack->Pop();
argOffset -= MachPtr;
break;
Expand All @@ -1810,7 +1809,8 @@ IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSl
IR::Instr * argInstr = nullptr;
IR::Instr * prevInstr = instr;

for (argInstr = m_argStack->Pop(); argInstr->m_opcode != Js::OpCode::StartCall; argInstr = m_argStack->Pop())
AssertOrFailFast(!this->m_argStack->Empty());
for (argInstr = m_argStack->Pop(); !m_argStack->Empty() && argInstr->m_opcode != Js::OpCode::StartCall; argInstr = m_argStack->Pop())
{
if (newOpcode == Js::OpCodeAsmJs::I_Call || newOpcode == Js::OpCodeAsmJs::ProfiledI_Call)
{
Expand Down Expand Up @@ -1840,10 +1840,10 @@ IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSl
count++;
}

Assert(argInstr->m_opcode == Js::OpCode::StartCall);
AssertOrFailFast(argInstr->m_opcode == Js::OpCode::StartCall);
argInstr->SetSrc1(IR::IntConstOpnd::New(count, TyUint16, m_func));

Assert(argOffset == 0);
AssertOrFailFast(argOffset == 0);
prevInstr->SetSrc2(argInstr->GetDst());

#ifdef ENABLE_SIMDJS
Expand Down
2 changes: 0 additions & 2 deletions lib/Backend/IRBuilderAsmJs.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,7 @@ class IRBuilderAsmJs
JitLoopBodyData* m_jitLoopBodyData = nullptr;
IRBuilderAsmJsSwitchAdapter m_switchAdapter;
SwitchIRBuilder m_switchBuilder;
#if DBG
uint32 m_offsetToInstructionCount;
#endif

#define BUILD_LAYOUT_DEF(layout, ...) void Build##layout (Js::OpCodeAsmJs, uint32, __VA_ARGS__);
#define Reg_Type Js::RegSlot
Expand Down
Loading