Skip to content

17-05 ChakraCore servicing release #2959

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

Merged
merged 12 commits into from
May 12, 2017
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
[CVE-2017-0228] Segment bug in the ReverseHelper.
Segments were getting reversed in the ReverseHelper call. This made the head segment, which is an inlined segment, to be as a next segment. If that segment becomes part of another array (say due to splice) and the original array goes away then the inlined segment will also go away and we potentially holdind the freed memory.
     Fixed that by detecting the inlined segment and convert to normal segment in the in EntryReverse API.
akroshg authored and rajatd committed May 10, 2017
commit 0cdbf2fe68f452c163ca5307cb9c57b118e966cc
58 changes: 57 additions & 1 deletion lib/Runtime/Library/JavascriptArray.cpp
Original file line number Diff line number Diff line change
@@ -5192,6 +5192,42 @@ namespace Js
}
}

template <typename T>
void JavascriptArray::CopyHeadIfInlinedHeadSegment(JavascriptArray *array, Recycler *recycler)
{
SparseArraySegmentBase* inlineHeadSegment = nullptr;
bool hasInlineSegment = false;

if (JavascriptNativeArray::Is(array))
{
if (JavascriptNativeFloatArray::Is(array))
{
inlineHeadSegment = DetermineInlineHeadSegmentPointer<JavascriptNativeFloatArray, 0, true>((JavascriptNativeFloatArray*)array);
}
else if (JavascriptNativeIntArray::Is(array))
{
inlineHeadSegment = DetermineInlineHeadSegmentPointer<JavascriptNativeIntArray, 0, true>((JavascriptNativeIntArray*)array);
}
Assert(inlineHeadSegment);
hasInlineSegment = (array->head == (SparseArraySegment<T>*)inlineHeadSegment);
}
else
{
hasInlineSegment = HasInlineHeadSegment(array->head->length);
}

if (hasInlineSegment)
{
SparseArraySegment<T>* headSeg = (SparseArraySegment<T>*)array->head;

SparseArraySegment<T>* newHeadSeg = SparseArraySegment<T>::template AllocateSegmentImpl<false>(recycler,
headSeg->left, headSeg->length, headSeg->size, headSeg->next);

newHeadSeg = SparseArraySegment<T>::CopySegment(recycler, newHeadSeg, headSeg->left, headSeg, headSeg->left, headSeg->length);
newHeadSeg->next = headSeg->next;
array->head = newHeadSeg;
}
}

Var JavascriptArray::EntryReverse(RecyclableObject* function, CallInfo callInfo, ...)
{
@@ -5289,7 +5325,6 @@ namespace Js
// Note : since we are reversing the whole segment below - the functionality is not spec compliant already.
length = pArr->length;

SparseArraySegmentBase* seg = pArr->head;
SparseArraySegmentBase *prevSeg = nullptr;
SparseArraySegmentBase *nextSeg = nullptr;
SparseArraySegmentBase *pinPrevSeg = nullptr;
@@ -5306,6 +5341,27 @@ namespace Js
isFloatArray = true;
}

// During the loop below we are going to reverse the segments list. The head segment will become the last segment.
// We have to verify that the current head segment is not the inilined segement, otherwise due to shuffling below, the inlined segment will no longer
// be the head and that can create issue down the line. Create new segment if it is an inilined segment.
if (pArr->head && pArr->head->next)
{
if (isIntArray)
{
CopyHeadIfInlinedHeadSegment<int32>(pArr, recycler);
}
else if (isFloatArray)
{
CopyHeadIfInlinedHeadSegment<double>(pArr, recycler);
}
else
{
CopyHeadIfInlinedHeadSegment<Var>(pArr, recycler);
}
}

SparseArraySegmentBase* seg = pArr->head;

while (seg)
{
nextSeg = seg->next;
2 changes: 2 additions & 0 deletions lib/Runtime/Library/JavascriptArray.h
Original file line number Diff line number Diff line change
@@ -553,6 +553,8 @@ namespace Js

virtual int32 HeadSegmentIndexOfHelper(Var search, uint32 &fromIndex, uint32 toIndex, bool includesAlgorithm, ScriptContext * scriptContext);

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

template<typename T>
static void ArraySpliceHelper(JavascriptArray* pNewArr, JavascriptArray* pArr, uint32 start, uint32 deleteLen,