Skip to content

Commit 0b9f3cd

Browse files
committed
Make Array concat responsive to side-effects of calling @@species create
to instantiate the destination array. Addresses CVE-2016-3214.
1 parent 15c0836 commit 0b9f3cd

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

lib/Runtime/Library/JavascriptArray.cpp

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3136,7 +3136,7 @@ namespace Js
31363136
}
31373137

31383138
bool converted;
3139-
if (JavascriptArray::IsAnyArray(aItem))
3139+
if (JavascriptArray::IsAnyArray(aItem) || remoteTypeIds[idxArg] == TypeIds_Array)
31403140
{
31413141
if (JavascriptNativeIntArray::Is(aItem)) // Fast path
31423142
{
@@ -3156,7 +3156,6 @@ namespace Js
31563156
ConcatArgs<uint>(pVarDestArray, remoteTypeIds, args, scriptContext, idxArg, idxDest);
31573157
return pVarDestArray;
31583158
}
3159-
31603159
if (converted)
31613160
{
31623161
// Copying the last array forced a conversion, so switch over to the var version
@@ -3167,8 +3166,6 @@ namespace Js
31673166
}
31683167
else
31693168
{
3170-
Assert(!JavascriptArray::IsAnyArray(aItem) && remoteTypeIds[idxArg] != TypeIds_Array);
3171-
31723169
if (TaggedInt::Is(aItem))
31733170
{
31743171
pDestArray->DirectSetItemAt(idxDest, (double)TaggedInt::ToInt32(aItem));
@@ -3327,9 +3324,52 @@ namespace Js
33273324
pDestObj = ArraySpeciesCreate(args[0], 0, scriptContext);
33283325
if (pDestObj)
33293326
{
3330-
isInt = JavascriptNativeIntArray::Is(pDestObj);
3331-
isFloat = !isInt && JavascriptNativeFloatArray::Is(pDestObj); // if we know it is an int short the condition to avoid a function call
3332-
isArray = isInt || isFloat || JavascriptArray::Is(pDestObj);
3327+
// Check the thing that species create made. If it's a native array that can't handle the source
3328+
// data, convert it. If it's a more conservative kind of array than the source data, indicate that
3329+
// so that the data will be converted on copy.
3330+
if (isInt)
3331+
{
3332+
if (JavascriptNativeIntArray::Is(pDestObj))
3333+
{
3334+
isArray = true;
3335+
}
3336+
else
3337+
{
3338+
isInt = false;
3339+
isFloat = JavascriptNativeFloatArray::Is(pDestObj);
3340+
isArray = JavascriptArray::Is(pDestObj);
3341+
}
3342+
}
3343+
else if (isFloat)
3344+
{
3345+
if (JavascriptNativeIntArray::Is(pDestObj))
3346+
{
3347+
JavascriptNativeIntArray::ToNativeFloatArray(JavascriptNativeIntArray::FromVar(pDestObj));
3348+
isArray = true;
3349+
}
3350+
else
3351+
{
3352+
isFloat = JavascriptNativeFloatArray::Is(pDestObj);
3353+
isArray = JavascriptArray::Is(pDestObj);
3354+
}
3355+
}
3356+
else
3357+
{
3358+
if (JavascriptNativeIntArray::Is(pDestObj))
3359+
{
3360+
JavascriptNativeIntArray::ToVarArray(JavascriptNativeIntArray::FromVar(pDestObj));
3361+
isArray = true;
3362+
}
3363+
else if (JavascriptNativeFloatArray::Is(pDestObj))
3364+
{
3365+
JavascriptNativeFloatArray::ToVarArray(JavascriptNativeFloatArray::FromVar(pDestObj));
3366+
isArray = true;
3367+
}
3368+
else
3369+
{
3370+
isArray = JavascriptArray::Is(pDestObj);
3371+
}
3372+
}
33333373
}
33343374

33353375
if (pDestObj == nullptr || isArray)

0 commit comments

Comments
 (0)