Skip to content

Commit

Permalink
[1.10>master] [MERGE #5444 @atulkatti] JULY 2018 Security Update
Browse files Browse the repository at this point in the history
Merge pull request #5444 from atulkatti:servicing/1807_1.10

JULY 2018 Security Update that addresses the following issues in ChakraCore.dll:
[CVE-2018-8275], [CVE-2018-8276], [CVE-2018-8279], [CVE-2018-8280], [CVE-2018-8283], [CVE-2018-8286], [CVE-2018-8287], [CVE-2018-8288], [CVE-2018-8290], [CVE-2018-8291], [CVE-2018-8294], [CVE-2018-8298]
  • Loading branch information
Atul Katti committed Jul 10, 2018
2 parents bff6dbd + 0f3f5be commit c567e4e
Show file tree
Hide file tree
Showing 29 changed files with 12,577 additions and 12,482 deletions.
8 changes: 4 additions & 4 deletions lib/Backend/GlobOpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,15 +845,15 @@ class GlobOpt
static void TrackByteCodeSymUsed(IR::Opnd * opnd, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed, PropertySym **pPropertySymUse);
static void TrackByteCodeSymUsed(IR::RegOpnd * opnd, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed);
static void TrackByteCodeSymUsed(StackSym * sym, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed);
void CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo);
void CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo, BVSparse<JitArenaAllocator>* argsToCapture);
void CaptureValuesFromScratch(
BasicBlock * block,
SListBase<ConstantStackSymValue>::EditingIterator & bailOutConstValuesIter,
SListBase<CopyPropSyms>::EditingIterator & bailOutCopyPropIter);
SListBase<ConstantStackSymValue>::EditingIterator & bailOutConstValuesIter, SListBase<CopyPropSyms>::EditingIterator & bailOutCopyPropIter,
BVSparse<JitArenaAllocator>* argsToCapture);
void CaptureValuesIncremental(
BasicBlock * block,
SListBase<ConstantStackSymValue>::EditingIterator & bailOutConstValuesIter,
SListBase<CopyPropSyms>::EditingIterator & bailOutCopyPropIter);
SListBase<CopyPropSyms>::EditingIterator & bailOutCopyPropIter, BVSparse<JitArenaAllocator>* argsToCapture);
void CaptureCopyPropValue(BasicBlock * block, Sym * sym, Value * val, SListBase<CopyPropSyms>::EditingIterator & bailOutCopySymsIter);
void CaptureArguments(BasicBlock *block, BailOutInfo * bailOutInfo, JitArenaAllocator *allocator);
void CaptureByteCodeSymUses(IR::Instr * instr);
Expand Down
33 changes: 26 additions & 7 deletions lib/Backend/GlobOptBailOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ GlobOpt::CaptureCopyPropValue(BasicBlock * block, Sym * sym, Value * val, SListB
void
GlobOpt::CaptureValuesFromScratch(BasicBlock * block,
SListBase<ConstantStackSymValue>::EditingIterator & bailOutConstValuesIter,
SListBase<CopyPropSyms>::EditingIterator & bailOutCopySymsIter)
SListBase<CopyPropSyms>::EditingIterator & bailOutCopySymsIter,
BVSparse<JitArenaAllocator>* argsToCapture)
{
Sym * sym = nullptr;
Value * value = nullptr;
Expand All @@ -49,6 +50,11 @@ GlobOpt::CaptureValuesFromScratch(BasicBlock * block,
}
NEXT_GLOBHASHTABLE_ENTRY;

if (argsToCapture)
{
block->globOptData.changedSyms->Or(argsToCapture);
}

FOREACH_BITSET_IN_SPARSEBV(symId, block->globOptData.changedSyms)
{
HashBucket<Sym*, Value*> * bucket = block->globOptData.symToValueMap->GetBucket(symId);
Expand Down Expand Up @@ -80,7 +86,8 @@ GlobOpt::CaptureValuesFromScratch(BasicBlock * block,
void
GlobOpt::CaptureValuesIncremental(BasicBlock * block,
SListBase<ConstantStackSymValue>::EditingIterator & bailOutConstValuesIter,
SListBase<CopyPropSyms>::EditingIterator & bailOutCopySymsIter)
SListBase<CopyPropSyms>::EditingIterator & bailOutCopySymsIter,
BVSparse<JitArenaAllocator>* argsToCapture)
{
CapturedValues * currCapturedValues = block->globOptData.capturedValues;
SListBase<ConstantStackSymValue>::Iterator iterConst(currCapturedValues ? &currCapturedValues->constantValues : nullptr);
Expand All @@ -90,6 +97,11 @@ GlobOpt::CaptureValuesIncremental(BasicBlock * block,

block->globOptData.changedSyms->Set(Js::Constants::InvalidSymID);

if (argsToCapture)
{
block->globOptData.changedSyms->Or(argsToCapture);
}

FOREACH_BITSET_IN_SPARSEBV(symId, block->globOptData.changedSyms)
{
Value * val = nullptr;
Expand Down Expand Up @@ -225,7 +237,7 @@ GlobOpt::CaptureValuesIncremental(BasicBlock * block,


void
GlobOpt::CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo)
GlobOpt::CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo, BVSparse<JitArenaAllocator>* argsToCapture)
{
if (!this->func->DoGlobOptsForGeneratorFunc())
{
Expand All @@ -244,11 +256,11 @@ GlobOpt::CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo)

if (!block->globOptData.capturedValues)
{
CaptureValuesFromScratch(block, bailOutConstValuesIter, bailOutCopySymsIter);
CaptureValuesFromScratch(block, bailOutConstValuesIter, bailOutCopySymsIter, argsToCapture);
}
else
{
CaptureValuesIncremental(block, bailOutConstValuesIter, bailOutCopySymsIter);
CaptureValuesIncremental(block, bailOutConstValuesIter, bailOutCopySymsIter, argsToCapture);
}

// attach capturedValues to bailOutInfo
Expand Down Expand Up @@ -892,6 +904,8 @@ GlobOpt::FillBailOutInfo(BasicBlock *block, BailOutInfo * bailOutInfo)
{
AssertMsg(!this->isCallHelper, "Bail out can't be inserted the middle of CallHelper sequence");

BVSparse<JitArenaAllocator>* argsToCapture = nullptr;

bailOutInfo->liveVarSyms = block->globOptData.liveVarSyms->CopyNew(this->func->m_alloc);
bailOutInfo->liveFloat64Syms = block->globOptData.liveFloat64Syms->CopyNew(this->func->m_alloc);
// The live int32 syms in the bailout info are only the syms resulting from lossless conversion to int. If the int32 value
Expand Down Expand Up @@ -971,7 +985,12 @@ GlobOpt::FillBailOutInfo(BasicBlock *block, BailOutInfo * bailOutInfo)
sym = opnd->GetStackSym();
Assert(this->currentBlock->globOptData.FindValue(sym));
// StackSym args need to be re-captured
this->currentBlock->globOptData.SetChangedSym(sym->m_id);
if (!argsToCapture)
{
argsToCapture = JitAnew(this->tempAlloc, BVSparse<JitArenaAllocator>, this->tempAlloc);
}

argsToCapture->Set(sym->m_id);
}

Assert(totalOutParamCount != 0);
Expand Down Expand Up @@ -1019,7 +1038,7 @@ GlobOpt::FillBailOutInfo(BasicBlock *block, BailOutInfo * bailOutInfo)

// Save the constant values that we know so we can restore them directly.
// This allows us to dead store the constant value assign.
this->CaptureValues(block, bailOutInfo);
this->CaptureValues(block, bailOutInfo, argsToCapture);
}

void
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/JnHelperMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ DECLSPEC_GUARDIGNORE _NOINLINE intptr_t GetNonTableMethodAddress(ThreadContextI
///----------------------------------------------------------------------------
intptr_t GetMethodOriginalAddress(ThreadContextInfo * context, JnHelperMethod helperMethod)
{
AssertOrFailFast(helperMethod >= 0 && helperMethod < IR::JnHelperMethodCount);
intptr_t address = GetHelperMethods()[static_cast<WORD>(helperMethod)];
if (address == 0)
{
Expand Down
5 changes: 5 additions & 0 deletions lib/JITServer/JITServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@ ServerAddDOMFastPathHelper(
Assert(false);
return RPC_S_INVALID_ARG;
}
if (helper < 0 || helper >= IR::JnHelperMethodCount)
{
Assert(UNREACHED);
return E_ACCESSDENIED;
}

return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT
{
Expand Down
12 changes: 8 additions & 4 deletions lib/Parser/Parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6345,7 +6345,9 @@ void Parser::ParseFncName(ParseNodeFnc * pnodeFnc, ushort flags, IdentPtr* pFncN
pnodeFnc->pnodeName = nullptr;

if ((m_token.tk != tkID || flags & fFncNoName)
&& (IsStrictMode() || (pnodeFnc->IsGenerator()) || m_token.tk != tkYIELD || fDeclaration)) // Function expressions can have the name yield even inside generator functions
&& (IsStrictMode() || fDeclaration
|| pnodeFnc->IsGenerator() || pnodeFnc->IsAsync()
|| (m_token.tk != tkYIELD && m_token.tk != tkAWAIT))) // Function expressions can have the name yield/await even inside generator/async functions
{
if (fDeclaration ||
m_token.IsReservedWord()) // For example: var x = (function break(){});
Expand All @@ -6355,7 +6357,7 @@ void Parser::ParseFncName(ParseNodeFnc * pnodeFnc, ushort flags, IdentPtr* pFncN
return;
}

Assert(m_token.tk == tkID || (m_token.tk == tkYIELD && !fDeclaration));
Assert(m_token.tk == tkID || (m_token.tk == tkYIELD && !fDeclaration) || (m_token.tk == tkAWAIT && !fDeclaration));

if (IsStrictMode())
{
Expand Down Expand Up @@ -8495,15 +8497,17 @@ ParseNodePtr Parser::ParseExpr(int oplMin,
// binding operator, be it unary or binary.
Error(ERRsyntax);
}
if (m_currentScope->GetScopeType() == ScopeType_Parameter)
if (m_currentScope->GetScopeType() == ScopeType_Parameter
|| (m_currentScope->GetScopeType() == ScopeType_Block && m_currentScope->GetEnclosingScope()->GetScopeType() == ScopeType_Parameter)) // Check whether this is a class definition inside param scope
{
Error(ERRsyntax);
}
}
else if (nop == knopAwait)
{
if (!this->GetScanner()->AwaitIsKeywordRegion() ||
m_currentScope->GetScopeType() == ScopeType_Parameter)
m_currentScope->GetScopeType() == ScopeType_Parameter ||
(m_currentScope->GetScopeType() == ScopeType_Block && m_currentScope->GetEnclosingScope()->GetScopeType() == ScopeType_Parameter)) // Check whether this is a class definition inside param scope
{
// As with the 'yield' keyword, the case where 'await' is scanned as a keyword (tkAWAIT)
// but the scanner is not treating await as a keyword (!this->GetScanner()->AwaitIsKeyword())
Expand Down
7 changes: 6 additions & 1 deletion lib/Runtime/Base/CrossSite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,12 @@ namespace Js
{
args.Values[i] = CrossSite::MarshalVar(targetScriptContext, args.Values[i]);
}
if (args.HasExtraArg())
if (args.HasNewTarget())
{
// Last value is new.target
args.Values[count] = CrossSite::MarshalVar(targetScriptContext, args.GetNewTarget());
}
else if (args.HasExtraArg())
{
// The final eval arg is a frame display that needs to be marshaled specially.
args.Values[count] = CrossSite::MarshalFrameDisplay(targetScriptContext, args.GetFrameDisplay());
Expand Down
7 changes: 7 additions & 0 deletions lib/Runtime/Base/ThreadServiceWrapperBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ bool ThreadServiceWrapperBase::ScheduleIdleCollect(uint ticks, bool scheduleAsTa

bool ThreadServiceWrapperBase::IdleCollect()
{
// Tracking service does not AddRef/Release the thread service and only keeps a function pointer and context parameter (this pointer)
// to execute the IdleCollect callback. It is possible that the tracking service gets destroyed as part of the collection
// during this IdleCollect. If that happens then we need to make sure ThreadService (which may be owned by the tracking service)
// is kept alive until this callback completes. Any pending timer is killed in the thread service destructor so we should not get
// any new callbacks after the thread service is destroyed.
AutoAddRefReleaseThreadService autoThreadServiceKeepAlive(this);

Assert(hasScheduledIdleCollect);
IDLE_COLLECT_VERBOSE_TRACE(_u("IdleCollect- reset hasScheduledIdleCollect\n"));
hasScheduledIdleCollect = false;
Expand Down
19 changes: 19 additions & 0 deletions lib/Runtime/Base/ThreadServiceWrapperBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,29 @@ class ThreadServiceWrapperBase : public ThreadServiceWrapper
virtual bool OnScheduleIdleCollect(uint delta, bool scheduleAsTask) = 0;
virtual void OnFinishIdleCollect() = 0;
virtual bool ShouldFinishConcurrentCollectOnIdleCallback() = 0;
virtual void AddRefThreadService() { /* do nothing */ };
virtual void ReleaseThreadService() { /* do nothing */ };

ThreadContext *GetThreadContext() { return threadContext; }

private:
class AutoAddRefReleaseThreadService
{
public:
AutoAddRefReleaseThreadService(ThreadServiceWrapperBase * threadService)
{
this->threadService = threadService;
threadService->AddRefThreadService();
}

~AutoAddRefReleaseThreadService()
{
threadService->ReleaseThreadService();
}

ThreadServiceWrapperBase * threadService;
};

static const unsigned int IdleTicks = 1000; // 1 second
static const unsigned int IdleFinishTicks = 100; // 100 ms;

Expand Down
4 changes: 2 additions & 2 deletions lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
//-------------------------------------------------------------------------------------------------------
// NOTE: If there is a merge conflict the correct fix is to make a new GUID.

// {3EB30F58-66E0-404B-BAE8-1D3CD23F866F}
// {18949169-1B93-4123-B34A-F42F1C1EAF9A}
const GUID byteCodeCacheReleaseFileVersion =
{ 0x3EB30F58, 0x66E0, 0x404B, { 0xBA, 0xE8, 0x1D, 0x3C, 0xD2, 0x3F, 0x86, 0x6F } };
{ 0x18949169, 0x1B93, 0x4123, { 0xB3, 0x4A, 0xF4, 0x2F, 0x1C, 0x1E, 0xAF, 0x9A } };
6 changes: 5 additions & 1 deletion lib/Runtime/InternalPropertyList.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ INTERNALPROPERTY(FrozenType) // Used to store shared frozen
INTERNALPROPERTY(StackTrace) // Stack trace object for Error.stack generation
INTERNALPROPERTY(StackTraceCache) // Cache of Error.stack string
INTERNALPROPERTY(WeakMapKeyMap) // WeakMap data stored on WeakMap key objects
INTERNALPROPERTY(HiddenObject) // Used to store hidden data for JS library code (Intl as an example will use this)
INTERNALPROPERTY(HiddenObject) // Used to store internal slot data for JS library code (Intl as an example will use this)
INTERNALPROPERTY(CachedUCollator) // Used to store cached UCollator objects for Intl.Collator
INTERNALPROPERTY(CachedUNumberFormat) // Used to store cached UNumberFormat objects for Intl.NumberFormat and Intl.PluralRules
INTERNALPROPERTY(CachedUDateFormat) // Used to store cached UDateFormat objects for Intl.DateTimeFormat
INTERNALPROPERTY(CachedUPluralRules) // Used to store cached UPluralRules objects for Intl.PluralRules
INTERNALPROPERTY(RevocableProxy) // Internal slot for [[RevokableProxy]] for revocable proxy in ES6
INTERNALPROPERTY(MutationBp) // Used to store strong reference to the mutation breakpoint object
#undef INTERNALPROPERTY
2 changes: 1 addition & 1 deletion lib/Runtime/Language/Arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ namespace Js

FrameDisplay* GetFrameDisplay() const
{
AssertOrFailFast(Info.Flags & CallFlags_ExtraArg);
AssertOrFailFast((Info.Flags & CallFlags_ExtraArg) && (!this->HasNewTarget()));

// There is an extra arg, so values should have Count + 1 members
return (FrameDisplay*)(this->Values[Info.Count]);
Expand Down
4 changes: 2 additions & 2 deletions lib/Runtime/Language/InterpreterHandler.inl
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,8 @@ EXDEF3_WMS(CUSTOM, LdLocalElemUndef, OP_LdLocalElemen
DEF3 (CUSTOM_L_R0, NewScIntArray, OP_NewScIntArray, Auxiliary)
DEF3 (CUSTOM_L_R0, NewScFltArray, OP_NewScFltArray, Auxiliary)
DEF3_WMS(CUSTOM_L_R0, ProfiledNewScArray, PROFILEDOP(OP_ProfiledNewScArray, OP_ProfiledNewScArray_NoProfile), ProfiledReg1Unsigned1)
DEF3 (CUSTOM_L_R0, ProfiledNewScIntArray, PROFILEDOP(OP_ProfiledNewScIntArray, OP_NewScIntArray), ProfiledAuxiliary)
DEF3 (CUSTOM_L_R0, ProfiledNewScFltArray, PROFILEDOP(OP_ProfiledNewScFltArray, OP_NewScFltArray), ProfiledAuxiliary)
DEF3 (CUSTOM_L_R0, ProfiledNewScIntArray, PROFILEDOP(ProfiledNewScIntArray<true>, ProfiledNewScIntArray<false>), ProfiledAuxiliary)
DEF3 (CUSTOM_L_R0, ProfiledNewScFltArray, PROFILEDOP(ProfiledNewScFltArray<true>, ProfiledNewScFltArray<false>), ProfiledAuxiliary)
DEF2_WMS(RegextoA1, NewRegEx, JavascriptRegExp::OP_NewRegEx)
EXDEF3_WMS(CUSTOM, InitClass, OP_InitClass, Class)
DEF2_WMS(BRBReturnP1toA1, BrOnEmpty, JavascriptOperators::OP_BrOnEmpty)
Expand Down
50 changes: 30 additions & 20 deletions lib/Runtime/Language/InterpreterStackFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5154,14 +5154,6 @@ namespace Js

void InterpreterStackFrame::OP_NewScIntArray(const unaligned OpLayoutAuxiliary * playout)
{
#if ENABLE_PROFILE_INFO
if (isAutoProfiling)
{
OP_ProfiledNewScIntArray(static_cast<const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> *>(playout));
return;
}
#endif

const Js::AuxArray<int32> *ints = Js::ByteCodeReader::ReadAuxArray<int32>(playout->Offset, this->GetFunctionBody());

JavascriptNativeIntArray *arr = scriptContext->GetLibrary()->CreateNativeIntArrayLiteral(ints->count);
Expand All @@ -5178,8 +5170,15 @@ namespace Js
}

#if ENABLE_PROFILE_INFO
void InterpreterStackFrame::OP_ProfiledNewScIntArray(const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> * playout)
template <bool Profiled>
void InterpreterStackFrame::ProfiledNewScIntArray(const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> * playout)
{
if (!Profiled && !isAutoProfiling)
{
OP_NewScIntArray(playout);
return;
}

const Js::AuxArray<int32> *ints = Js::ByteCodeReader::ReadAuxArray<int32>(playout->Offset, this->GetFunctionBody());

Js::ProfileId profileId = playout->profileId;
Expand Down Expand Up @@ -5239,18 +5238,16 @@ namespace Js

SetReg(playout->R0, arr);
}
#else
template <bool Profiled>
void InterpreterStackFrame::ProfiledNewScIntArray(const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> * playout)
{
OP_NewScIntArray(playout);
}
#endif

void InterpreterStackFrame::OP_NewScFltArray(const unaligned OpLayoutAuxiliary * playout)
{
#if ENABLE_PROFILE_INFO
if (isAutoProfiling)
{
OP_ProfiledNewScFltArray(static_cast<const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> *>(playout));
return;
}
#endif

const Js::AuxArray<double> *doubles = Js::ByteCodeReader::ReadAuxArray<double>(playout->Offset, this->GetFunctionBody());

JavascriptNativeFloatArray *arr = scriptContext->GetLibrary()->CreateNativeFloatArrayLiteral(doubles->count);
Expand All @@ -5267,8 +5264,15 @@ namespace Js
}

#if ENABLE_PROFILE_INFO
void InterpreterStackFrame::OP_ProfiledNewScFltArray(const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> * playout)
template <bool Profiled>
void InterpreterStackFrame::ProfiledNewScFltArray(const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> * playout)
{
if (!Profiled && !isAutoProfiling)
{
OP_NewScFltArray(playout);
return;
}

const Js::AuxArray<double> *doubles = Js::ByteCodeReader::ReadAuxArray<double>(playout->Offset, this->GetFunctionBody());

Js::ProfileId profileId = playout->profileId;
Expand Down Expand Up @@ -5304,6 +5308,12 @@ namespace Js

SetReg(playout->R0, arr);
}
#else
template <bool Profiled>
void InterpreterStackFrame::ProfiledNewScFltArray(const unaligned OpLayoutDynamicProfile<OpLayoutAuxiliary> * playout)
{
OP_NewScFltArray(playout);
}
#endif

void InterpreterStackFrame::OP_SetArraySegmentVars(const unaligned OpLayoutAuxiliary * playout)
Expand Down Expand Up @@ -6213,7 +6223,7 @@ namespace Js
}

template <class T, bool Profiled>
void InterpreterStackFrame::OP_NewScObjArray_Impl(const unaligned T* playout, const Js::AuxArray<uint32> *spreadIndices)
void InterpreterStackFrame::OP_ProfiledNewScObjArray_Impl(const unaligned T* playout, const Js::AuxArray<uint32> *spreadIndices)
{
// Always profile this operation when auto-profiling so that array type changes are tracked
#if ENABLE_PROFILE_INFO
Expand All @@ -6222,7 +6232,7 @@ namespace Js
Assert(!Profiled);
#endif
{
OP_NewScObject_Impl<T, Profiled, false>(playout, Js::Constants::NoInlineCacheIndex, spreadIndices);
OP_NewScObjArray_Impl<T, Profiled>(playout, spreadIndices);
return;
}

Expand Down
Loading

0 comments on commit c567e4e

Please sign in to comment.