Skip to content

Commit 090b258

Browse files
author
Thomas Moore (CHAKRA)
committed
[1.11>master] [1.10>1.11] [MERGE #5764 @thomasmo] October 2018 Security Update
Merge pull request #5764 from thomasmo:1810 October 2018 Security Update that addresses the following issues in ChakraCore: CVE-2018-8473 CVE-2018-8500 CVE-2018-8503 CVE-2018-8505 CVE-2018-8510 CVE-2018-8511 CVE-2018-8513
2 parents 42ba7b9 + bc9e381 commit 090b258

10 files changed

+51
-58
lines changed

lib/Backend/GlobOpt.cpp

+12-39
Original file line numberDiff line numberDiff line change
@@ -1017,27 +1017,16 @@ BOOL GlobOpt::PRE::PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate)
10171017
// Create instr to put in landing pad for compensation
10181018
Assert(IsPREInstrCandidateLoad(ldInstrInLoop->m_opcode));
10191019

1020-
IR::Instr * ldInstr = InsertPropertySymPreloadWithoutDstInLandingPad(ldInstrInLoop, loop, propertySym);
1020+
IR::Instr * ldInstr = InsertPropertySymPreloadInLandingPad(ldInstrInLoop, loop, propertySym);
10211021
if (!ldInstr)
10221022
{
10231023
return false;
10241024
}
10251025

10261026
Assert(ldInstr->GetDst() == nullptr);
1027-
if (ldInstrInLoop->GetDst())
1028-
{
1029-
Assert(ldInstrInLoop->GetDst()->IsRegOpnd());
1030-
if (ldInstrInLoop->GetDst()->AsRegOpnd()->m_sym != symStore)
1031-
{
1032-
ldInstr->SetDst(IR::RegOpnd::New(symStore->AsStackSym(), TyVar, this->globOpt->func));
1033-
loop->fieldPRESymStores->Set(symStore->m_id);
1034-
}
1035-
else
1036-
{
1037-
ldInstr->SetDst(ldInstrInLoop->GetDst()->Copy(ldInstrInLoop->m_func));
1038-
}
1039-
landingPad->globOptData.liveVarSyms->Set(ldInstr->GetDst()->AsRegOpnd()->m_sym->m_id);
1040-
}
1027+
ldInstr->SetDst(IR::RegOpnd::New(symStore->AsStackSym(), TyVar, this->globOpt->func));
1028+
loop->fieldPRESymStores->Set(symStore->m_id);
1029+
landingPad->globOptData.liveVarSyms->Set(symStore->m_id);
10411030

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

@@ -3318,7 +3307,7 @@ GlobOpt::OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef, I
33183307
// Can this be done in one call?
33193308
if (!this->prePassInstrMap->ContainsKey(sym->m_id))
33203309
{
3321-
this->prePassInstrMap->AddNew(sym->m_id, instr);
3310+
this->prePassInstrMap->AddNew(sym->m_id, instr->CopyWithoutDst());
33223311
}
33233312
}
33243313
}
@@ -17492,7 +17481,7 @@ GlobOpt::PRE::InsertSymDefinitionInLandingPad(StackSym * sym, Loop * loop, Sym *
1749217481
// #1 is done next. #2 and #3 are done as part of preloading T1.y
1749317482

1749417483
// Insert T1 = o.x
17495-
if (!InsertPropertySymPreloadInLandingPad(symDefInstr, loop, propSym))
17484+
if (!InsertPropertySymPreloadInLandingPad(symDefInstr->Copy(), loop, propSym))
1749617485
{
1749717486
return false;
1749817487
}
@@ -17505,7 +17494,7 @@ GlobOpt::PRE::InsertSymDefinitionInLandingPad(StackSym * sym, Loop * loop, Sym *
1750517494
if (loop->landingPad->globOptData.IsLive(*objPtrCopyPropSym))
1750617495
{
1750717496
// insert T1 = o.x
17508-
if (!InsertPropertySymPreloadInLandingPad(symDefInstr, loop, propSym))
17497+
if (!InsertPropertySymPreloadInLandingPad(symDefInstr->Copy(), loop, propSym))
1750917498
{
1751017499
return false;
1751117500
}
@@ -17593,25 +17582,6 @@ GlobOpt::PRE::InsertInstrInLandingPad(IR::Instr * instr, Loop * loop)
1759317582

1759417583
IR::Instr *
1759517584
GlobOpt::PRE::InsertPropertySymPreloadInLandingPad(IR::Instr * ldInstr, Loop * loop, PropertySym * propertySym)
17596-
{
17597-
IR::Instr * instr = InsertPropertySymPreloadWithoutDstInLandingPad(ldInstr, loop, propertySym);
17598-
if (!instr)
17599-
{
17600-
return nullptr;
17601-
}
17602-
17603-
if (ldInstr->GetDst())
17604-
{
17605-
instr->SetDst(ldInstr->GetDst()->Copy(ldInstr->m_func));
17606-
instr->GetDst()->SetIsJITOptimizedReg(true);
17607-
loop->landingPad->globOptData.liveVarSyms->Set(instr->GetDst()->GetStackSym()->m_id);
17608-
}
17609-
17610-
return instr;
17611-
}
17612-
17613-
IR::Instr *
17614-
GlobOpt::PRE::InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * ldInstr, Loop * loop, PropertySym * propertySym)
1761517585
{
1761617586
IR::SymOpnd *ldSrc = ldInstr->GetSrc1()->AsSymOpnd();
1761717587

@@ -17626,8 +17596,6 @@ GlobOpt::PRE::InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * ldInstr
1762617596
}
1762717597
}
1762817598

17629-
ldInstr = ldInstr->CopyWithoutDst();
17630-
1763117599
// Consider: Shouldn't be necessary once we have copy-prop in prepass...
1763217600
ldInstr->GetSrc1()->AsSymOpnd()->m_sym = propertySym;
1763317601
ldSrc = ldInstr->GetSrc1()->AsSymOpnd();
@@ -17641,6 +17609,11 @@ GlobOpt::PRE::InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * ldInstr
1764117609
ldInstr->ReplaceSrc1(newPropSymOpnd);
1764217610
}
1764317611

17612+
if (ldInstr->GetDst())
17613+
{
17614+
loop->landingPad->globOptData.liveVarSyms->Set(ldInstr->GetDst()->GetStackSym()->m_id);
17615+
}
17616+
1764417617
InsertInstrInLandingPad(ldInstr, loop);
1764517618

1764617619
return ldInstr;

lib/Backend/GlobOpt.h

-1
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,6 @@ class GlobOpt::PRE
10301030
void FindPossiblePRECandidates(Loop *loop, JitArenaAllocator *alloc);
10311031
void PreloadPRECandidates(Loop *loop);
10321032
BOOL PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate);
1033-
IR::Instr * InsertPropertySymPreloadWithoutDstInLandingPad(IR::Instr * origLdInstr, Loop * loop, PropertySym * propertySym);
10341033
IR::Instr * InsertPropertySymPreloadInLandingPad(IR::Instr * origLdInstr, Loop * loop, PropertySym * propertySym);
10351034
void InsertInstrInLandingPad(IR::Instr * instr, Loop * loop);
10361035
bool InsertSymDefinitionInLandingPad(StackSym * sym, Loop * loop, Sym ** objPtrCopyPropSym);

lib/Backend/GlobOptArrays.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ void GlobOpt::ArraySrcOpt::CheckVirtualArrayBounds()
330330
{
331331
Assert(instr->m_opcode == Js::OpCode::InlineArrayPush ||
332332
instr->m_opcode == Js::OpCode::InlineArrayPop ||
333-
instr->m_opcode == Js::OpCode::LdLen_A);
333+
instr->m_opcode == Js::OpCode::LdLen_A ||
334+
instr->m_opcode == Js::OpCode::IsIn);
334335
}
335336

336337
eliminatedLowerBoundCheck = true;
@@ -1998,6 +1999,8 @@ void GlobOpt::ArraySrcOpt::Optimize()
19981999
{
19992000
TRACE_TESTTRACE_PHASE_INSTR(Js::Phase::BoundCheckEliminationPhase, instr, _u("Eliminating IsIn\n"));
20002001

2002+
globOpt->CaptureByteCodeSymUses(instr);
2003+
20012004
instr->m_opcode = Js::OpCode::Ld_A;
20022005

20032006
IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(func->GetScriptContextInfo()->GetTrueAddr(), IR::AddrOpndKindDynamicVar, func, true);

lib/Backend/GlobOptBailOut.cpp

+15-4
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ GlobOpt::CaptureValuesIncremental(BasicBlock * block,
201201
NEXT_BITSET_IN_SPARSEBV
202202

203203
// If, after going over the set of changed syms since the last time we captured values,
204-
// there are remaining unprocessed entries in the current captured values set,
204+
// there are remaining unprocessed entries in the current captured values set,
205205
// they can simply be copied over to the new bailout info.
206206
while (hasConstValue)
207207
{
@@ -272,7 +272,7 @@ GlobOpt::CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo, BVSparse<Ji
272272
bailOutInfo->capturedValues->copyPropSyms.Clear(this->func->m_alloc);
273273
bailOutCopySymsIter.SetNext(&bailOutInfo->capturedValues->copyPropSyms);
274274
bailOutInfo->capturedValues->copyPropSyms = capturedValues.copyPropSyms;
275-
275+
276276
// In pre-pass only bailout info created should be for the loop header, and that doesn't take into account the back edge.
277277
// Don't use the captured values on that bailout for incremental capturing of values.
278278
if (!PHASE_OFF(Js::IncrementalBailoutPhase, func) && !this->IsLoopPrePass())
@@ -591,6 +591,8 @@ GlobOpt::TrackCalls(IR::Instr * instr)
591591
this->EndTrackCall(instr);
592592

593593
InlineeFrameInfo* inlineeFrameInfo = InlineeFrameInfo::New(instr->m_func->m_alloc);
594+
inlineeFrameInfo->functionSymStartValue = instr->GetSrc1()->GetSym() ?
595+
CurrentBlockData()->FindValue(instr->GetSrc1()->GetSym()) : nullptr;
594596
inlineeFrameInfo->floatSyms = CurrentBlockData()->liveFloat64Syms->CopyNew(this->alloc);
595597
inlineeFrameInfo->intSyms = CurrentBlockData()->liveInt32Syms->MinusNew(CurrentBlockData()->liveLossyInt32Syms, this->alloc);
596598
inlineeFrameInfo->varSyms = CurrentBlockData()->liveVarSyms->CopyNew(this->alloc);
@@ -605,7 +607,7 @@ GlobOpt::TrackCalls(IR::Instr * instr)
605607
instr->m_func->cachedInlineeFrameInfo = inlineeFrameInfo;
606608
}
607609
break;
608-
}
610+
}
609611

610612
case Js::OpCode::EndCallForPolymorphicInlinee:
611613
// Have this opcode mimic the functions of both InlineeStart and InlineeEnd in the bailout block of a polymorphic call inlined using fixed methods.
@@ -780,6 +782,15 @@ void GlobOpt::RecordInlineeFrameInfo(IR::Instr* inlineeEnd)
780782
}
781783
else
782784
{
785+
// If the value of the functionObject symbol has changed between the inlineeStart and the inlineeEnd,
786+
// we don't record the inlinee frame info (see OS#18318884).
787+
Assert(frameInfo->functionSymStartValue != nullptr);
788+
if (!frameInfo->functionSymStartValue->IsEqualTo(CurrentBlockData()->FindValue(functionObject->m_sym)))
789+
{
790+
argInstr->m_func->DisableCanDoInlineArgOpt();
791+
return true;
792+
}
793+
783794
frameInfo->function = InlineFrameInfoValue(functionObject->m_sym);
784795
}
785796
}
@@ -1171,7 +1182,7 @@ GlobOpt::MaySrcNeedBailOnImplicitCall(IR::Opnd const * opnd, Value const * val)
11711182
case IR::OpndKindReg:
11721183
// Only need implicit call if the operation will call ToPrimitive and we haven't prove
11731184
// that it is already a primitive
1174-
return
1185+
return
11751186
!(val && val->GetValueInfo()->IsPrimitive()) &&
11761187
!opnd->AsRegOpnd()->GetValueType().IsPrimitive() &&
11771188
!opnd->AsRegOpnd()->m_sym->IsInt32() &&

lib/Backend/InlineeFrameInfo.h

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#pragma once
77

8+
class Value;
9+
810
struct BailoutConstantValue {
911
public:
1012
void InitIntConstValue(int32 value) { this->type = TyInt32; this->u.intConst.value = (IntConstType)value; };
@@ -150,6 +152,7 @@ struct InlineeFrameInfo
150152
BVSparse<JitArenaAllocator>* floatSyms;
151153
BVSparse<JitArenaAllocator>* intSyms;
152154
BVSparse<JitArenaAllocator>* varSyms;
155+
Value* functionSymStartValue;
153156

154157
bool isRecorded;
155158

lib/Runtime/Base/FunctionBody.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,7 @@ namespace Js
21192119
{
21202120
FunctionTypeWeakRefList* typeList = EnsureFunctionObjectTypeList();
21212121

2122-
Assert(functionType != deferredPrototypeType);
2122+
Assert(functionType != deferredPrototypeType && functionType != undeferredFunctionType);
21232123
Recycler * recycler = this->GetScriptContext()->GetRecycler();
21242124
FunctionTypeWeakRef* weakRef = recycler->CreateWeakReferenceHandle(functionType);
21252125
typeList->SetAtFirstFreeSpot(weakRef);

lib/Runtime/Base/FunctionBody.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -1088,8 +1088,10 @@ namespace Js
10881088
{
10891089
func(this->deferredPrototypeType);
10901090
}
1091-
// NOTE: We deliberately do not map the undeferredFunctionType here, since it's in the list
1092-
// of registered function object types we processed above.
1091+
if (this->undeferredFunctionType)
1092+
{
1093+
func(this->undeferredFunctionType);
1094+
}
10931095
}
10941096

10951097
static uint GetOffsetOfDeferredPrototypeType() { return static_cast<uint>(offsetof(Js::FunctionProxy, deferredPrototypeType)); }

lib/Runtime/Language/JavascriptOperators.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -4953,13 +4953,18 @@ using namespace Js;
49534953
}
49544954
else if (instanceType == TypeIds_NativeIntArray)
49554955
{
4956-
// Only accept tagged int. Also covers case for MissingItem
4956+
// Only accept tagged int.
49574957
if (!TaggedInt::Is(value))
49584958
{
49594959
return false;
49604960
}
49614961
int32 intValue = 0;
49624962
if (!MemsetConversion<int32, JavascriptConversion::ToInt32>(value, scriptContext, &intValue))
4963+
{
4964+
return false;
4965+
}
4966+
// Special case for missing item
4967+
if (SparseArraySegment<int32>::IsMissingItem(&intValue))
49634968
{
49644969
return false;
49654970
}

lib/Runtime/Library/JavascriptArray.cpp

+3-9
Original file line numberDiff line numberDiff line change
@@ -1490,13 +1490,11 @@ using namespace Js;
14901490

14911491
bool isTaggedInt = TaggedInt::Is(item);
14921492
bool isTaggedIntMissingValue = false;
1493-
#ifdef TARGET_64
14941493
if (isTaggedInt)
14951494
{
14961495
int32 iValue = TaggedInt::ToInt32(item);
14971496
isTaggedIntMissingValue = Js::SparseArraySegment<int32>::IsMissingItem(&iValue);
14981497
}
1499-
#endif
15001498
if (isTaggedInt && !isTaggedIntMissingValue)
15011499
{
15021500
// This is taggedInt case and we verified that item is not missing value in AMD64.
@@ -3426,16 +3424,12 @@ using namespace Js;
34263424
{
34273425
if (TaggedInt::Is(aItem))
34283426
{
3429-
pDestArray->DirectSetItemAt(idxDest, TaggedInt::ToInt32(aItem));
3427+
int32 int32Value = TaggedInt::ToInt32(aItem);
3428+
Assert(!SparseArraySegment<int32>::IsMissingItem(&int32Value));
3429+
pDestArray->DirectSetItemAt(idxDest, int32Value);
34303430
}
34313431
else
34323432
{
3433-
#if DBG
3434-
int32 int32Value;
3435-
Assert(
3436-
JavascriptNumber::TryGetInt32Value(JavascriptNumber::GetValue(aItem), &int32Value) &&
3437-
!SparseArraySegment<int32>::IsMissingItem(&int32Value));
3438-
#endif
34393433
pDestArray->DirectSetItemAt(idxDest, static_cast<int32>(JavascriptNumber::GetValue(aItem)));
34403434
}
34413435
++idxDest;

lib/Runtime/Types/PathTypeHandler.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,9 @@ namespace Js
15121512
if (!(attributes[descriptor->GetDataPropertyIndex<false>()] & ObjectSlotAttr_Accessor))
15131513
{
15141514
// Setter without a getter; this is a stale entry, so ignore it
1515+
// Just consume the slot so no descriptor refers to it.
1516+
Assert(i == newTypeHandler->nextPropertyIndex);
1517+
::Math::PostInc(newTypeHandler->nextPropertyIndex);
15151518
continue;
15161519
}
15171520
Assert(oldTypeHandler->GetSetterSlotIndex(descriptor->GetDataPropertyIndex<false>()) == newTypeHandler->nextPropertyIndex);

0 commit comments

Comments
 (0)