Skip to content

Commit 0cdbf2f

Browse files
akroshgrajatd
authored andcommitted
[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.
1 parent 0440807 commit 0cdbf2f

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

lib/Runtime/Library/JavascriptArray.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5192,6 +5192,42 @@ namespace Js
51925192
}
51935193
}
51945194

5195+
template <typename T>
5196+
void JavascriptArray::CopyHeadIfInlinedHeadSegment(JavascriptArray *array, Recycler *recycler)
5197+
{
5198+
SparseArraySegmentBase* inlineHeadSegment = nullptr;
5199+
bool hasInlineSegment = false;
5200+
5201+
if (JavascriptNativeArray::Is(array))
5202+
{
5203+
if (JavascriptNativeFloatArray::Is(array))
5204+
{
5205+
inlineHeadSegment = DetermineInlineHeadSegmentPointer<JavascriptNativeFloatArray, 0, true>((JavascriptNativeFloatArray*)array);
5206+
}
5207+
else if (JavascriptNativeIntArray::Is(array))
5208+
{
5209+
inlineHeadSegment = DetermineInlineHeadSegmentPointer<JavascriptNativeIntArray, 0, true>((JavascriptNativeIntArray*)array);
5210+
}
5211+
Assert(inlineHeadSegment);
5212+
hasInlineSegment = (array->head == (SparseArraySegment<T>*)inlineHeadSegment);
5213+
}
5214+
else
5215+
{
5216+
hasInlineSegment = HasInlineHeadSegment(array->head->length);
5217+
}
5218+
5219+
if (hasInlineSegment)
5220+
{
5221+
SparseArraySegment<T>* headSeg = (SparseArraySegment<T>*)array->head;
5222+
5223+
SparseArraySegment<T>* newHeadSeg = SparseArraySegment<T>::template AllocateSegmentImpl<false>(recycler,
5224+
headSeg->left, headSeg->length, headSeg->size, headSeg->next);
5225+
5226+
newHeadSeg = SparseArraySegment<T>::CopySegment(recycler, newHeadSeg, headSeg->left, headSeg, headSeg->left, headSeg->length);
5227+
newHeadSeg->next = headSeg->next;
5228+
array->head = newHeadSeg;
5229+
}
5230+
}
51955231

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

5292-
SparseArraySegmentBase* seg = pArr->head;
52935328
SparseArraySegmentBase *prevSeg = nullptr;
52945329
SparseArraySegmentBase *nextSeg = nullptr;
52955330
SparseArraySegmentBase *pinPrevSeg = nullptr;
@@ -5306,6 +5341,27 @@ namespace Js
53065341
isFloatArray = true;
53075342
}
53085343

5344+
// During the loop below we are going to reverse the segments list. The head segment will become the last segment.
5345+
// 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
5346+
// be the head and that can create issue down the line. Create new segment if it is an inilined segment.
5347+
if (pArr->head && pArr->head->next)
5348+
{
5349+
if (isIntArray)
5350+
{
5351+
CopyHeadIfInlinedHeadSegment<int32>(pArr, recycler);
5352+
}
5353+
else if (isFloatArray)
5354+
{
5355+
CopyHeadIfInlinedHeadSegment<double>(pArr, recycler);
5356+
}
5357+
else
5358+
{
5359+
CopyHeadIfInlinedHeadSegment<Var>(pArr, recycler);
5360+
}
5361+
}
5362+
5363+
SparseArraySegmentBase* seg = pArr->head;
5364+
53095365
while (seg)
53105366
{
53115367
nextSeg = seg->next;

lib/Runtime/Library/JavascriptArray.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,8 @@ namespace Js
553553

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

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

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

0 commit comments

Comments
 (0)