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

JS constants not initialised properly causing JsValue::null() to leak memory

Open J-Cake opened this issue 7 months ago • 0 comments

Describe the Bug

A wasm-bindgen - generated module returns bindings which initialise tables used to allow Rust to generate JS values. The emitted bindings (usually the *_js_bg.js file) contains a __wbindgen_init_externref_table() function which correctly initialises these constants. However, the current system does not call this function.

Steps to Reproduce

  1. Generate a wasm-bindgen module which calls JsValue::null()
  2. Load the bindings using the code:
import mod from '#mod/main.wasm';
import * as util from '#mod/util.js';

const wasm = new WebAssembly.Instance(new WebAssembly.Module(mod), {
    "./mod_js_bg.js": util as any,
});

util.__wbg_set_wasm(wasm.exports);

export * from '#mod/util.js';
  1. This can be observed more reliably by "doing something" before printing out null values because the uninitialised constants table will leak memory. For example, I was implementing a REPL for a parser I implemented in Rust. When the expression returned a null value, it is cast back to a JsValue::null(). Before the initialisation, this call would print out the value I typed into the REPL which first caused it to return null. If that were a password for example, that could be a major security issue.

If applicable, add a link to a test case (as a zip file or link to a repository we can clone).

Expected Behavior

The utility module's __wbg_set_wasm() function should also initialise the wasm context by calling the necessary initialisation functions.

Actual Behavior

A clear and concise description of what actually happened.

If applicable, add screenshots to help explain your problem.

Negative Positive
Image Image

The two screenshots show the results of enabling/disabling the initialisation. In both cases, the query {a:0} returns a null value (represented by the keyword nothing).

The left screenshot shows the conversion of a Nothing to a JsValue("{a:0}") while the right shows the correct transformation into a JsValue(null)

Additional Context

A non-functional real-life example can be found here.

clone that exact tag, build the module and run the example repl.ts. Enter {a:0} to observe error.

J-Cake avatar Apr 25 '25 21:04 J-Cake