This bug is one instance of a bug which which ""might"" be experienced on all platforms except MacOSX, since Bug 984018.
This bug is a MoveResolver bug which might read a non-normalized double from the stack, which contains stale data including forged data with a JS::Value pointer meant to read/write any memory. One can potentially use this bug to get random memory access.
The problem here is that MSinCos uses passABIArg to call
js::math_sincos_impl. However passABIArg is unable to handle cycles with a random base pointer given as address, it has to be a register which is not used by the call convention as an argument register.
Here references to the Sin and Cos values are reserved and referenced by the
params register which is freely allocated by the register allocator. This implies that if the
params register matches the second argument register. This implies that the second reference would be equal to the first one, and that the
js::math_sincos_impl function would not override the stack space. This stack space is then read back out of the stack pointer and stored as a double value, which is assumed to be in a canonical form (NaN). Making this double value an argument of a non-JIT-ed function will allow the non-JIT-ed function to interpret this non-cannonicalized double as a JS::Value, with a forged pointer to the stack, which might emulate an Array with wide bounds.
While double checking the generated code on all platform, I noticed that this is a non-issue because Sin and Cos address computations happen to be inverted, so even if there is a register override case, it would only be overwritten with the same value or not be reused.
The instruction order written here:
Is inverted by:
And thus even if the code is incorrect, this is non-exploitable, and works as expected except for this assertion. (I am amazed …)
I will note that I have not seen any other instance of this issue while proof-reading the rest of uses of passABIArg.