wasm-bindgen icon indicating copy to clipboard operation
wasm-bindgen copied to clipboard

Reading wrong address when memory usage exceeds 2GB

Open b-inary opened this issue 3 years ago • 1 comments

Describe the Bug

When memory usage exceeds 2GB, the glue code generated by wasm-pack reads the wrong address.

Steps to Reproduce

The following program uses 3GB of memory.

#[wasm_bindgen]
pub struct HugeData {
    _data1: Vec<u32>,
    data2: Vec<u32>,
}

#[wasm_bindgen]
impl HugeData {
    pub fn new() -> Self {
        let mut _data1 = vec![0; 3 << 27]; // 1.5 GB
        let mut data2 = vec![0; 3 << 27]; // 1.5 GB
        for i in 0..(3 << 27) {
            _data1[i as usize] = i;
            data2[i as usize] = i + (3 << 27);
        }
        Self { _data1, data2 }
    }

    pub fn get_last_element_as_boxed_slice(&self) -> Box<[u32]> {
        self.data2[(3 << 27) - 1..].to_vec().into_boxed_slice()
    }
}

Expected Behavior

get_last_element_as_boxed_slice() should return Uint32Array [ 805306367 ], where 805306367 is equal to (3 << 28) - 1.

Actual Behavior

In my environment, Uint32Array [ 537182218 ] was returned.

The glue code generated by wasm-pack is as follows:

/**
* @returns {Uint32Array}
*/
get_last_element_as_boxed_slice() {
    try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
        wasm.hugedata_get_last_element_as_boxed_slice(retptr, this.ptr);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v0 = getArrayU32FromWasm0(r0, r1).slice();
        wasm.__wbindgen_free(r0, r1 * 4);
        return v0;
    } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
    }
}

Here, var r0 is a signed 32-bit integer, and it is negative when memory usage exceeds 2GB. Therefore, getArrayU32FromWasm0(r0, r1) reads memory of negative address, which causes this bug.

b-inary avatar Jun 20 '22 13:06 b-inary

Thanks for the report! I think the generated JS hasn't ever been audited for pointers >= 2GB unfortunately. In theory this can be solved by sprinkling some >>> 0 additions in the code generation but I don't know how to best handle make sure everything is covered.

alexcrichton avatar Jun 20 '22 23:06 alexcrichton