The spread operator in JavaScript allows an array to be treated as function parameters using the following syntax:
var a = [1,2];
f(...a);
This is implemented in the JavascriptFunction::SpreadArgs function in Chakra (https://github.com/Microsoft/ChakraCore/blob/master/lib/Runtime/Library/JavascriptFunction.cpp).
On line 1054 of this function, the following code is used to spread an array:
if (argsIndex + arr->GetLength() > destArgs.Info.Count)
{
AssertMsg(false, "The array length has changed since we allocated the destArgs buffer?");
Throw::FatalInternalError();
}
for (uint32 j = 0; j < arr->GetLength(); j++)
{
Var element;
if (!arr->DirectGetItemAtFull(j, &element))
{
element = undefined;
}
destArgs.Values[argsIndex++] = element;
}
When DirectGetItemAtFull accesses the array, if an element of the array is undefined, it will fall back to the prototype of the array. In some situations, for example if the prototype is a Proxy, this can execute user-defined script, which can change the length of the array, meaning that the call can overflow destArgs.Values, even through the length has already been checked. Note that this check also has a potential integer overflow, which should also probably be fixed as a part of this issue.
A full PoC is attached.
This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.