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

October 2018 Security Update #5764

Merged
merged 7 commits into from
Oct 9, 2018
53 changes: 13 additions & 40 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,28 +1013,17 @@ BOOL GlobOpt::PRE::PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate)
// Create instr to put in landing pad for compensation
Assert(IsPREInstrCandidateLoad(ldInstrInLoop->m_opcode));

IR::Instr * ldInstr = InsertPropertySymPreloadWithoutDstInLandingPad(ldInstrInLoop, loop, propertySym);
IR::Instr * ldInstr = InsertPropertySymPreloadInLandingPad(ldInstrInLoop, loop, propertySym);
if (!ldInstr)
{
return false;
}

Assert(ldInstr->GetDst() == nullptr);
if (ldInstrInLoop->GetDst())
{
Assert(ldInstrInLoop->GetDst()->IsRegOpnd());
if (ldInstrInLoop->GetDst()->AsRegOpnd()->m_sym != symStore)
{
ldInstr->SetDst(IR::RegOpnd::New(symStore->AsStackSym(), TyVar, this->globOpt->func));
loop->fieldPRESymStores->Set(symStore->m_id);
}
else
{
ldInstr->SetDst(ldInstrInLoop->GetDst()->Copy(ldInstrInLoop->m_func));
}
landingPad->globOptData.liveVarSyms->Set(ldInstr->GetDst()->AsRegOpnd()->m_sym->m_id);
}

ldInstr->SetDst(IR::RegOpnd::New(symStore->AsStackSym(), TyVar, this->globOpt->func));
loop->fieldPRESymStores->Set(symStore->m_id);
landingPad->globOptData.liveVarSyms->Set(symStore->m_id);

Value * objPtrValue = landingPad->globOptData.FindValue(objPtrSym);

objPtrCopyPropSym = objPtrCopyPropSym ? objPtrCopyPropSym : objPtrValue ? landingPad->globOptData.GetCopyPropSym(objPtrSym, objPtrValue) : nullptr;
Expand Down Expand Up @@ -3310,7 +3299,7 @@ GlobOpt::OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef, I
// Can this be done in one call?
if (!this->prePassInstrMap->ContainsKey(sym->m_id))
{
this->prePassInstrMap->AddNew(sym->m_id, instr);
this->prePassInstrMap->AddNew(sym->m_id, instr->CopyWithoutDst());
}
}
}
Expand Down Expand Up @@ -17235,7 +17224,7 @@ GlobOpt::PRE::InsertSymDefinitionInLandingPad(StackSym * sym, Loop * loop, Sym *
// #1 is done next. #2 and #3 are done as part of preloading T1.y

// Insert T1 = o.x
if (!InsertPropertySymPreloadInLandingPad(symDefInstr, loop, propSym))
if (!InsertPropertySymPreloadInLandingPad(symDefInstr->Copy(), loop, propSym))
{
return false;
}
Expand All @@ -17248,7 +17237,7 @@ GlobOpt::PRE::InsertSymDefinitionInLandingPad(StackSym * sym, Loop * loop, Sym *
if (loop->landingPad->globOptData.IsLive(*objPtrCopyPropSym))
{
// insert T1 = o.x
if (!InsertPropertySymPreloadInLandingPad(symDefInstr, loop, propSym))
if (!InsertPropertySymPreloadInLandingPad(symDefInstr->Copy(), loop, propSym))
{
return false;
}
Expand Down Expand Up @@ -17336,25 +17325,6 @@ GlobOpt::PRE::InsertInstrInLandingPad(IR::Instr * instr, Loop * loop)

IR::Instr *
GlobOpt::PRE::InsertPropertySymPreloadInLandingPad(IR::Instr * ldInstr, Loop * loop, PropertySym * propertySym)
{
IR::Instr * instr = InsertPropertySymPreloadWithoutDstInLandingPad(ldInstr, loop, propertySym);
if (!instr)
{
return nullptr;
}

if (ldInstr->GetDst())
{
instr->SetDst(ldInstr->GetDst()->Copy(ldInstr->m_func));
instr->GetDst()->SetIsJITOptimizedReg(true);
loop->landingPad->globOptData.liveVarSyms->Set(instr->GetDst()->GetStackSym()->m_id);
}

return instr;
}

IR::Instr *
GlobOpt::PRE::InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * ldInstr, Loop * loop, PropertySym * propertySym)
{
IR::SymOpnd *ldSrc = ldInstr->GetSrc1()->AsSymOpnd();

Expand All @@ -17369,8 +17339,6 @@ GlobOpt::PRE::InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * ldInstr
}
}

ldInstr = ldInstr->CopyWithoutDst();

// Consider: Shouldn't be necessary once we have copy-prop in prepass...
ldInstr->GetSrc1()->AsSymOpnd()->m_sym = propertySym;
ldSrc = ldInstr->GetSrc1()->AsSymOpnd();
Expand All @@ -17384,6 +17352,11 @@ GlobOpt::PRE::InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * ldInstr
ldInstr->ReplaceSrc1(newPropSymOpnd);
}

if (ldInstr->GetDst())
{
loop->landingPad->globOptData.liveVarSyms->Set(ldInstr->GetDst()->GetStackSym()->m_id);
}

InsertInstrInLandingPad(ldInstr, loop);

return ldInstr;
Expand Down
1 change: 0 additions & 1 deletion lib/Backend/GlobOpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,6 @@ class GlobOpt::PRE
void FindPossiblePRECandidates(Loop *loop, JitArenaAllocator *alloc);
void PreloadPRECandidates(Loop *loop);
BOOL PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate);
IR::Instr * InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * origLdInstr, Loop * loop, PropertySym * propertySym);
IR::Instr * InsertPropertySymPreloadInLandingPad(IR::Instr * origLdInstr, Loop * loop, PropertySym * propertySym);
void InsertInstrInLandingPad(IR::Instr * instr, Loop * loop);
bool InsertSymDefinitionInLandingPad(StackSym * sym, Loop * loop, Sym ** objPtrCopyPropSym);
Expand Down
5 changes: 4 additions & 1 deletion lib/Backend/GlobOptArrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ void GlobOpt::ArraySrcOpt::CheckVirtualArrayBounds()
{
Assert(instr->m_opcode == Js::OpCode::InlineArrayPush ||
instr->m_opcode == Js::OpCode::InlineArrayPop ||
instr->m_opcode == Js::OpCode::LdLen_A);
instr->m_opcode == Js::OpCode::LdLen_A ||
instr->m_opcode == Js::OpCode::IsIn);
}

eliminatedLowerBoundCheck = true;
Expand Down Expand Up @@ -1988,6 +1989,8 @@ void GlobOpt::ArraySrcOpt::Optimize()
{
TRACE_TESTTRACE_PHASE_INSTR(Js::Phase::BoundCheckEliminationPhase, instr, _u("Eliminating IsIn\n"));

globOpt->CaptureByteCodeSymUses(instr);

instr->m_opcode = Js::OpCode::Ld_A;

IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(func->GetScriptContextInfo()->GetTrueAddr(), IR::AddrOpndKindDynamicVar, func, true);
Expand Down
11 changes: 11 additions & 0 deletions lib/Backend/GlobOptBailOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ GlobOpt::TrackCalls(IR::Instr * instr)
instr->m_func->m_hasInlineArgsOpt = true;
InlineeFrameInfo* frameInfo = InlineeFrameInfo::New(func->m_alloc);
instr->m_func->frameInfo = frameInfo;
frameInfo->functionSymStartValue = instr->GetSrc1()->GetSym() ?
CurrentBlockData()->FindValue(instr->GetSrc1()->GetSym()) : nullptr;
frameInfo->floatSyms = CurrentBlockData()->liveFloat64Syms->CopyNew(this->alloc);
frameInfo->intSyms = CurrentBlockData()->liveInt32Syms->MinusNew(CurrentBlockData()->liveLossyInt32Syms, this->alloc);
frameInfo->varSyms = CurrentBlockData()->liveVarSyms->CopyNew(this->alloc);
Expand Down Expand Up @@ -762,6 +764,15 @@ void GlobOpt::RecordInlineeFrameInfo(IR::Instr* inlineeEnd)
}
else
{
// If the value of the functionObject symbol has changed between the inlineeStart and the inlineeEnd,
// we don't record the inlinee frame info (see OS#18318884).
Assert(frameInfo->functionSymStartValue != nullptr);
if (!frameInfo->functionSymStartValue->IsEqualTo(CurrentBlockData()->FindValue(functionObject->m_sym)))
{
argInstr->m_func->DisableCanDoInlineArgOpt();
return true;
}

frameInfo->function = InlineFrameInfoValue(functionObject->m_sym);
}
}
Expand Down
3 changes: 3 additions & 0 deletions lib/Backend/InlineeFrameInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#pragma once

class Value;

struct BailoutConstantValue {
public:
void InitIntConstValue(int32 value) { this->type = TyInt32; this->u.intConst.value = (IntConstType)value; };
Expand Down Expand Up @@ -150,6 +152,7 @@ struct InlineeFrameInfo
BVSparse<JitArenaAllocator>* floatSyms;
BVSparse<JitArenaAllocator>* intSyms;
BVSparse<JitArenaAllocator>* varSyms;
Value* functionSymStartValue;

bool isRecorded;

Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Base/FunctionBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2105,7 +2105,7 @@ namespace Js
{
FunctionTypeWeakRefList* typeList = EnsureFunctionObjectTypeList();

Assert(functionType != deferredPrototypeType);
Assert(functionType != deferredPrototypeType && functionType != undeferredFunctionType);
Recycler * recycler = this->GetScriptContext()->GetRecycler();
FunctionTypeWeakRef* weakRef = recycler->CreateWeakReferenceHandle(functionType);
typeList->SetAtFirstFreeSpot(weakRef);
Expand Down
6 changes: 4 additions & 2 deletions lib/Runtime/Base/FunctionBody.h
Original file line number Diff line number Diff line change
Expand Up @@ -1088,8 +1088,10 @@ namespace Js
{
func(this->deferredPrototypeType);
}
// NOTE: We deliberately do not map the undeferredFunctionType here, since it's in the list
// of registered function object types we processed above.
if (this->undeferredFunctionType)
{
func(this->undeferredFunctionType);
}
}

static uint GetOffsetOfDeferredPrototypeType() { return static_cast<uint>(offsetof(Js::FunctionProxy, deferredPrototypeType)); }
Expand Down
7 changes: 6 additions & 1 deletion lib/Runtime/Language/JavascriptOperators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4950,13 +4950,18 @@ using namespace Js;
}
else if (instanceType == TypeIds_NativeIntArray)
{
// Only accept tagged int. Also covers case for MissingItem
// Only accept tagged int.
if (!TaggedInt::Is(value))
{
return false;
}
int32 intValue = 0;
if (!MemsetConversion<int32, JavascriptConversion::ToInt32>(value, scriptContext, &intValue))
{
return false;
}
// Special case for missing item
if (SparseArraySegment<int32>::IsMissingItem(&intValue))
{
return false;
}
Expand Down
12 changes: 3 additions & 9 deletions lib/Runtime/Library/JavascriptArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,13 +1499,11 @@ using namespace Js;

bool isTaggedInt = TaggedInt::Is(item);
bool isTaggedIntMissingValue = false;
#ifdef TARGET_64
if (isTaggedInt)
{
int32 iValue = TaggedInt::ToInt32(item);
isTaggedIntMissingValue = Js::SparseArraySegment<int32>::IsMissingItem(&iValue);
}
#endif
if (isTaggedInt && !isTaggedIntMissingValue)
{
// This is taggedInt case and we verified that item is not missing value in AMD64.
Expand Down Expand Up @@ -3426,16 +3424,12 @@ using namespace Js;
{
if (TaggedInt::Is(aItem))
{
pDestArray->DirectSetItemAt(idxDest, TaggedInt::ToInt32(aItem));
int32 int32Value = TaggedInt::ToInt32(aItem);
Assert(!SparseArraySegment<int32>::IsMissingItem(&int32Value));
pDestArray->DirectSetItemAt(idxDest, int32Value);
}
else
{
#if DBG
int32 int32Value;
Assert(
JavascriptNumber::TryGetInt32Value(JavascriptNumber::GetValue(aItem), &int32Value) &&
!SparseArraySegment<int32>::IsMissingItem(&int32Value));
#endif
pDestArray->DirectSetItemAt(idxDest, static_cast<int32>(JavascriptNumber::GetValue(aItem)));
}
++idxDest;
Expand Down
3 changes: 3 additions & 0 deletions lib/Runtime/Types/PathTypeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,9 @@ namespace Js
if (!(attributes[descriptor->GetDataPropertyIndex<false>()] & ObjectSlotAttr_Accessor))
{
// Setter without a getter; this is a stale entry, so ignore it
// Just consume the slot so no descriptor refers to it.
Assert(i == newTypeHandler->nextPropertyIndex);
::Math::PostInc(newTypeHandler->nextPropertyIndex);
continue;
}
Assert(oldTypeHandler->GetSetterSlotIndex(descriptor->GetDataPropertyIndex<false>()) == newTypeHandler->nextPropertyIndex);
Expand Down