# CVE-2020-1380: Internet Explorer JScript9 Use-after-Free

JScript9 JIT mismodels Array.prototype.push on arguments and ToPrimitive callbacks, letting a valueOf callback detach a Float32Array and cause UAF in IE.

- Payout: Real-world hack
- Severity: high
- Program: Microsoft Internet Explorer
- Credited: Maddie Stone & Samuel Groß, Project Zero (Originally posted on [Project Zero blog](https://googleprojectzero.blogspot.com/p/rca.html) 2020-08-24)
- Disclosed: 2020-08-11
- CVE: CVE-2020-1380
- Write-up quality: 9/10
- Original: https://github.com/googleprojectzero/0days-in-the-wild/blob/main/0day-RCAs/2020/CVE-2020-1380.md
- Library page: https://bugbountylibrary.com/r/p0%3ACVE-2020-1380
- Tags: domain:browser impact:rce kind:incident platform:project-zero sev:high technique:chained technique:source-review vuln:dos vuln:memory-corruption

**Target:** JScript9 JavaScript engine (jscript9.dll) in Internet Explorer
**Root cause:** JIT fails to model that Array.prototype.push on the arguments object mutates stack argument values, then assumes value1 stays an int and that ToPrimitive on it cannot invoke callbacks.
**Steps:**
1. Compile opt() 10000x with int args and Float32Array arr so JIT infers value2 is int.
2. Inside opt, set `arguments.push = Array.prototype.push; arguments.length = 0; arguments.push(value2)` to overwrite value1 with value2.
3. Pass an Object with valueOf as value2; JIT still treats value1 as int when doing `arr[1] = value1`.
4. In valueOf, detach arr.buffer via `worker.postMessage(0,[arr.buffer])` and spin to force GC, causing UAF.
**How found:** Authors speculate: unlikely via pure RE; plausible via generative fuzzing (Fuzzilli), grey-box JIT IR inspection experimenting with side-effect modelling edge cases (detaching ArrayBuffer during indexed access through type conversion), or porting public V8/JSC regression tests to JScript9.
**Exploitation:** Force JIT compile, detach ArrayBuffer in valueOf callback, trigger GC via sleep loop, reallocate freed memory with LargeHeapBlock so the store overwrites Allocated Block Count (+0x14) with 0, then allocate/free arrays to get two JavascriptNativeIntArray objects sharing a head pointer for OOB r/w, build DataView arbitrary r/w, leak stack via LinktoBeginning<ThreadContext>, compute jscript9.dll base from vftable and imports, ROP to VirtualProtect shellcode, then load CVE-2020-0986 EoP.
**Escalation:** Chained with CVE-2020-0986 (patched two months earlier) for privilege escalation after code execution in the renderer.
**Insight:** JS JIT side-effect modelling is a rich bug class: try mutating the arguments object via borrowed Array methods and detaching typed-array buffers inside valueOf/toString callbacks invoked by indexed stores.
