Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
[Merge chakra-core/ChakraCore@93ec291cff] [MERGE #3166 @jianchun] 17-…
Browse files Browse the repository at this point in the history
…06 ChakraCore servicing release

Merge pull request #3166 from jianchun:1706

Fixes the following CVEs impacting ChakraCore:

[CVE-2017-0228]
[CVE-2017-8499]
[CVE-2017-8518]
[CVE-2017-8520]
[CVE-2017-8522]
[CVE-2017-8524]
[CVE-2017-8548]
  • Loading branch information
chakrabot authored and kfarnung committed Jun 15, 2017
1 parent ddb361e commit acb450a
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 40 deletions.
5 changes: 5 additions & 0 deletions deps/chakrashim/core/Build/Chakra.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ClCompile>
<PreprocessorDefinitions>
%(PreprocessorDefinitions);
_CHAKRACOREBUILD;
_WIN32_WINNT=$(Win32_WinNTVersion);
WINVER=$(Win32_WinNTVersion);
WIN32_LEAN_AND_MEAN=1
Expand Down Expand Up @@ -52,6 +53,10 @@
<Optimization Condition="'$(ENABLE_CODECOVERAGE)'=='true'">Disabled</Optimization>
</ClCompile>

<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_CHAKRACOREBUILD</PreprocessorDefinitions>
</ResourceCompile>

<Link>
<!-- ======== For Code Coverage ======== -->
<AdditionalOptions Condition="'$(ENABLE_CODECOVERAGE)'=='true'">%(AdditionalOptions) /DEBUGTYPE:CV,FIXUP</AdditionalOptions>
Expand Down
2 changes: 1 addition & 1 deletion deps/chakrashim/core/Build/Common.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<AdditionalOptions>%(AdditionalOptions) -sal_local</AdditionalOptions>
</Midl>
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_CHAKRACOREBUILD;NOMINMAX;USE_EDGEMODE_JSRT</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);NOMINMAX;USE_EDGEMODE_JSRT</PreprocessorDefinitions>
<!-- Some of our STDMETHOD can throw
TODO: Code review STDMETHOD and separate out API that can throw and those that can't -->
<PreprocessorDefinitions>%(PreprocessorDefinitions);COM_STDMETHOD_CAN_THROW</PreprocessorDefinitions>
Expand Down
48 changes: 40 additions & 8 deletions deps/chakrashim/core/lib/Backend/Inline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4674,16 +4674,22 @@ Inline::MapFormals(Func *inlinee,
{
break;
}

int excess;
uint restFuncFormalCount = 0;
if (instr->m_func != inlinee)
{
// this can happen only when we are inlining a function which has inlined an apply call with the arguments object
formalCount = instr->m_func->GetJITFunctionBody()->GetInParamsCount();
restFuncFormalCount = instr->m_func->GetJITFunctionBody()->GetInParamsCount();
Assert(restFuncFormalCount < 1 << 24); // 24 bits for arg count (see CallInfo.h)
excess = actualCount - restFuncFormalCount;
}
else
{
excess = actualCount - formalCount;
}

IR::Opnd *restDst = instr->GetDst();

Assert(actualCount < 1 << 24 && formalCount < 1 << 24); // 24 bits for arg count (see CallInfo.h)
int excess = actualCount - formalCount;

if (excess < 0)
{
Expand All @@ -4701,11 +4707,37 @@ Inline::MapFormals(Func *inlinee,
IR::Instr *newArrInstr = IR::Instr::New(Js::OpCode::NewScArray, restDst, IR::IntConstOpnd::New(excess, TyUint32, inlinee), inlinee);
instr->InsertBefore(newArrInstr);

for (uint i = formalCount; i < actualCount; ++i)
if (instr->m_func != inlinee)
{
IR::IndirOpnd *arrayLocOpnd = IR::IndirOpnd::New(restDst->AsRegOpnd(), i - formalCount, TyVar, inlinee);
IR::Instr *stElemInstr = IR::Instr::New(Js::OpCode::StElemC, arrayLocOpnd, argOutsExtra[i]->GetBytecodeArgOutCapture()->GetDst(), inlinee);
instr->InsertBefore(stElemInstr);
uint index = 0;
for (uint i = restFuncFormalCount; i < min(actualCount, formalCount); ++i)
{
IR::IndirOpnd *arrayLocOpnd = IR::IndirOpnd::New(restDst->AsRegOpnd(), index, TyVar, inlinee);
IR::Instr *stElemInstr = IR::Instr::New(Js::OpCode::StElemC, arrayLocOpnd, argOuts[i]->GetBytecodeArgOutCapture()->GetDst(), inlinee);
instr->InsertBefore(stElemInstr);
index++;
}
for (uint i = max(formalCount, restFuncFormalCount); i < actualCount; ++i)
{
IR::IndirOpnd *arrayLocOpnd = IR::IndirOpnd::New(restDst->AsRegOpnd(), index, TyVar, inlinee);
IR::Instr *stElemInstr = IR::Instr::New(Js::OpCode::StElemC, arrayLocOpnd, argOutsExtra[i]->GetBytecodeArgOutCapture()->GetDst(), inlinee);
instr->InsertBefore(stElemInstr);
index++;
}
AssertMsg(index == (uint)excess, "Incorrect rest args built");
if (index != (uint)excess)
{
throw Js::OperationAbortedException();
}
}
else
{
for (uint i = formalCount; i < actualCount; ++i)
{
IR::IndirOpnd *arrayLocOpnd = IR::IndirOpnd::New(restDst->AsRegOpnd(), i - formalCount, TyVar, inlinee);
IR::Instr *stElemInstr = IR::Instr::New(Js::OpCode::StElemC, arrayLocOpnd, argOutsExtra[i]->GetBytecodeArgOutCapture()->GetDst(), inlinee);
instr->InsertBefore(stElemInstr);
}
}

instr->Remove();
Expand Down
12 changes: 12 additions & 0 deletions deps/chakrashim/core/lib/Backend/Lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15889,10 +15889,22 @@ Lowerer::GenerateFastElemIIntIndexCommon(
// For typed array, call ToNumber before we fallThrough.
if (instr->GetSrc1()->GetType() == TyVar && !instr->GetSrc1()->GetValueType().IsPrimitive())
{
// Enter an ophelper block
IR::LabelInstr * opHelper = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
instr->InsertBefore(opHelper);

IR::Instr *toNumberInstr = IR::Instr::New(Js::OpCode::Call, this->m_func);
toNumberInstr->SetSrc1(instr->GetSrc1());
instr->InsertBefore(toNumberInstr);

if (BailOutInfo::IsBailOutOnImplicitCalls(bailOutKind))
{
// Bail out if this conversion triggers implicit calls.
toNumberInstr = toNumberInstr->ConvertToBailOutInstr(instr->GetBailOutInfo(), bailOutKind);
IR::Instr * instrShare = instr->ShareBailOut();
LowerBailTarget(instrShare);
}

LowerUnaryHelperMem(toNumberInstr, IR::HelperOp_ConvNumber_Full);
}
InsertBranch(Js::OpCode::Br, labelFallthrough, instr); //Jump to fallThrough
Expand Down
6 changes: 5 additions & 1 deletion deps/chakrashim/core/lib/JITServer/JITServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,11 +422,15 @@ ServerCleanupScriptContext(
return RPC_S_INVALID_ARG;
}

if (!scriptContextInfo->IsClosed())
{
scriptContextInfo->Close();
ServerContextManager::UnRegisterScriptContext(scriptContextInfo);
}
// This tells the run-time, when it is marshalling the out
// parameters, that the context handle has been closed normally.
*scriptContextInfoAddress = nullptr;

Assert(scriptContextInfo->IsClosed());
HeapDelete(scriptContextInfo);

return S_OK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6435,7 +6435,7 @@ namespace Js
aParent = CrossSite::MarshalVar(scriptContext, aParent);
if (i == length)
{
length += 8;
length = UInt16Math::Add(length, 8);
FrameDisplay * tmp = RecyclerNewPlus(scriptContext->GetRecycler(), length * sizeof(void*), FrameDisplay, length);
js_memcpy_s((char*)tmp + tmp->GetOffsetOfScopes(), tmp->GetLength() * sizeof(void *), (char*)pDisplay + pDisplay->GetOffsetOfScopes(), pDisplay->GetLength() * sizeof(void*));
pDisplay = tmp;
Expand Down Expand Up @@ -6493,10 +6493,10 @@ namespace Js

FrameDisplay *pDisplay = nullptr;
FrameDisplay *envDisplay = (FrameDisplay*)argEnv;
uint16 length = envDisplay->GetLength() + 1;
uint16 length = UInt16Math::Add(envDisplay->GetLength(), 1);

pDisplay = RecyclerNewPlus(scriptContext->GetRecycler(), length * sizeof(void*), FrameDisplay, length);
for (int j = 0; j < length - 1; j++)
for (uint16 j = 0; j < length - 1; j++)
{
pDisplay->SetItem(j + 1, envDisplay->GetItem(j));
}
Expand Down
48 changes: 27 additions & 21 deletions deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5253,16 +5253,30 @@ namespace Js

if (hasInlineSegment)
{
SparseArraySegmentBase* headSegBase = array->head;
SparseArraySegment<T>* headSeg = (SparseArraySegment<T>*)headSegBase;
AnalysisAssert(array->head);
SparseArraySegment<T>* newHeadSeg = array->ReallocNonLeafSegment((SparseArraySegment<T>*)PointerValue(array->head), array->head->next);
array->head = newHeadSeg;
}
}

AnalysisAssert(headSeg);
SparseArraySegment<T>* newHeadSeg = SparseArraySegment<T>::template AllocateSegmentImpl<false>(recycler,
headSeg->left, headSeg->length, headSeg->size, headSeg->next);
template <typename T>
void JavascriptArray::ReallocateNonLeafLastSegmentIfLeaf(JavascriptArray * arr, Recycler * recycler)
{
Assert(arr->head && arr->head->next); // Doesn't make sense to reallocate a leaf last segment as a non-leaf if its not going to point to any other segments.

newHeadSeg = SparseArraySegment<T>::CopySegment(recycler, newHeadSeg, headSeg->left, headSeg, headSeg->left, headSeg->length);
newHeadSeg->next = headSeg->next;
array->head = newHeadSeg;
// TODO: Consider utilizing lastUsedSegment once we fix CopyHeadIfInlinedHeadSegment in that respect.
SparseArraySegmentBase *lastSeg = nullptr;
SparseArraySegmentBase *seg = arr->head;
while (seg)
{
lastSeg = seg;
seg = seg->next;
}

if (SparseArraySegmentBase::IsLeafSegment(lastSeg, recycler))
{
AnalysisAssert(lastSeg);
arr->ReallocNonLeafSegment((SparseArraySegment<T>*)lastSeg, lastSeg->next, true /*forceNonLeaf*/);
}
}

Expand Down Expand Up @@ -5369,6 +5383,8 @@ namespace Js
bool isIntArray = false;
bool isFloatArray = false;

pArr->ClearSegmentMap(); // Just dump the segment map on reverse

if (JavascriptNativeIntArray::Is(pArr))
{
isIntArray = true;
Expand All @@ -5386,10 +5402,12 @@ namespace Js
if (isIntArray)
{
CopyHeadIfInlinedHeadSegment<int32>(pArr, recycler);
ReallocateNonLeafLastSegmentIfLeaf<int32>(pArr, recycler);
}
else if (isFloatArray)
{
CopyHeadIfInlinedHeadSegment<double>(pArr, recycler);
ReallocateNonLeafLastSegmentIfLeaf<double>(pArr, recycler);
}
else
{
Expand Down Expand Up @@ -5437,33 +5455,21 @@ namespace Js
}

pArr->head = prevSeg;

// Just dump the segment map on reverse
pArr->ClearSegmentMap();
pArr->InvalidateLastUsedSegment(); // lastUsedSegment might be 0-length and discarded above

if (isIntArray)
{
if (pArr->head && pArr->head->next && SparseArraySegmentBase::IsLeafSegment(pArr->head, recycler))
{
pArr->ReallocNonLeafSegment(SparseArraySegment<int32>::From(pArr->head), pArr->head->next);
}
pArr->EnsureHeadStartsFromZero<int32>(recycler);
}
else if (isFloatArray)
{
if (pArr->head && pArr->head->next && SparseArraySegmentBase::IsLeafSegment(pArr->head, recycler))
{
pArr->ReallocNonLeafSegment(SparseArraySegment<double>::From(pArr->head), pArr->head->next);
}
pArr->EnsureHeadStartsFromZero<double>(recycler);
}
else
{
pArr->EnsureHeadStartsFromZero<Var>(recycler);
}

pArr->InvalidateLastUsedSegment(); // lastUsedSegment might be 0-length and discarded above

#ifdef VALIDATE_ARRAY
pArr->ValidateArray();
#endif
Expand Down
4 changes: 3 additions & 1 deletion deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ namespace Js
JavascriptArray(JavascriptArray * instance, bool boxHead);

template<typename T> inline void LinkSegments(SparseArraySegment<T>* prev, SparseArraySegment<T>* current);
template<typename T> inline SparseArraySegment<T>* ReallocNonLeafSegment(SparseArraySegment<T>* seg, SparseArraySegmentBase* nextSeg);
template<typename T> inline SparseArraySegment<T>* ReallocNonLeafSegment(SparseArraySegment<T>* seg, SparseArraySegmentBase* nextSeg, bool forceNonLeaf = false);
void TryAddToSegmentMap(Recycler* recycler, SparseArraySegmentBase* seg);

private:
Expand Down Expand Up @@ -575,6 +575,8 @@ namespace Js

template<typename T>
static void CopyHeadIfInlinedHeadSegment(JavascriptArray *array, Recycler *recycler);
template<typename T>
static void ReallocateNonLeafLastSegmentIfLeaf(JavascriptArray * arr, Recycler * recycler);

template<typename T>
static void ArraySpliceHelper(JavascriptArray* pNewArr, JavascriptArray* pArr, uint32 start, uint32 deleteLen,
Expand Down
12 changes: 10 additions & 2 deletions deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.inl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ namespace Js
}

template<typename T>
inline SparseArraySegment<T>* JavascriptArray::ReallocNonLeafSegment(SparseArraySegment<T> *seg, SparseArraySegmentBase* nextSeg)
inline SparseArraySegment<T>* JavascriptArray::ReallocNonLeafSegment(SparseArraySegment<T> *seg, SparseArraySegmentBase* nextSeg, bool forceNonLeaf)
{
// Find the segment prior to seg.
SparseArraySegmentBase *prior = nullptr;
Expand All @@ -106,8 +106,16 @@ namespace Js
Assert(prior->next);
}
}
SparseArraySegment<T> *newSeg = nullptr;
Recycler *recycler = this->GetScriptContext()->GetRecycler();
SparseArraySegment<T> *newSeg = SparseArraySegment<T>::AllocateSegment(recycler, seg->left, seg->length, nextSeg);
if (forceNonLeaf)
{
newSeg = SparseArraySegment<T>::template AllocateSegmentImpl<false /*isLeaf*/>(recycler, seg->left, seg->length, nextSeg);
}
else
{
newSeg = SparseArraySegment<T>::AllocateSegment(recycler, seg->left, seg->length, nextSeg);
}
CopyArray(newSeg->elements, seg->length, seg->elements, seg->length);

LinkSegmentsCommon(prior, newSeg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ namespace Js
if (this->IsAccessor)
{
Assert(this->Data == NoSlots);
if (addingLetConstGlobal)
{
this->Data = nextPropertyIndex++;
}
}
else if (addingLetConstGlobal)
{
Expand All @@ -165,7 +169,7 @@ namespace Js
this->Getter = nextPropertyIndex++;
}
this->Attributes |= PropertyLetConstGlobal;
Assert(GetDataPropertyIndex<false>() != NoSlots);
Assert((addingLetConstGlobal ? GetDataPropertyIndex<true>() : GetDataPropertyIndex<false>()) != NoSlots);
}

template <typename TPropertyIndex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ namespace Js

if(isUnordered)
{
newTypeHandler->CopyUnorderedStateFrom(*AsUnordered());
newTypeHandler->CopyUnorderedStateFrom(*AsUnordered(), instance);
}
else
{
Expand Down Expand Up @@ -2685,6 +2685,7 @@ namespace Js
->AddProperty(instance, propertyKey, value, attributes, info, flags, possibleSideEffects);
}

// CONSIDER: Do this after TryReuseDeletedPropertyIndex. If we can reuse slots, no need to grow right now.
if (this->GetSlotCapacity() <= nextPropertyIndex)
{
if (this->GetSlotCapacity() >= MaxPropertyIndexSize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,30 @@ namespace Js

private:
template<class OtherTPropertyIndex, class OtherTMapKey, bool OtherIsNotExtensibleSupported>
void CopyUnorderedStateFrom(const SimpleDictionaryUnorderedTypeHandler<OtherTPropertyIndex, OtherTMapKey, OtherIsNotExtensibleSupported> &other)
void CopyUnorderedStateFrom(const SimpleDictionaryUnorderedTypeHandler<OtherTPropertyIndex, OtherTMapKey, OtherIsNotExtensibleSupported> &other,
DynamicObject *const object)
{
CompileAssert(sizeof(TPropertyIndex) >= sizeof(OtherTPropertyIndex));
if (other.deletedPropertyIndex != PropertyIndexRanges<OtherTPropertyIndex>::NoSlots)
{
deletedPropertyIndex = other.deletedPropertyIndex;

// If terminator values are different, walk to end of chain and update terminator value
if ((int)PropertyIndexRanges<TPropertyIndex>::NoSlots != (int)PropertyIndexRanges<OtherTPropertyIndex>::NoSlots)
{
OtherTPropertyIndex cur = other.deletedPropertyIndex;
for (;;)
{
OtherTPropertyIndex next = static_cast<OtherTPropertyIndex>(TaggedInt::ToInt32(object->GetSlot(cur)));
if (next == PropertyIndexRanges<OtherTPropertyIndex>::NoSlots)
{
this->SetSlotUnchecked(object, cur, TaggedInt::ToVarUnchecked(PropertyIndexRanges<TPropertyIndex>::NoSlots));
break;
}

cur = next;
}
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions deps/chakrashim/core/test/LetConst/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -379,4 +379,9 @@
<compile-flags>-args summary -endargs</compile-flags>
</default>
</test>
<test>
<default>
<files>shadowedsetter.js</files>
</default>
</test>
</regress-exe>
18 changes: 18 additions & 0 deletions deps/chakrashim/core/test/LetConst/shadowedsetter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

evaluate = WScript.LoadScript;

__defineSetter__("x", function () { });

evaluate(`
let x = 'let';
Object.defineProperty(this, "x", { value:
0xdec0 })
if (x === 'let' && this.x === 57024)
{
WScript.Echo('pass');
}
`);

0 comments on commit acb450a

Please sign in to comment.