[Memory64] Wasm table imports don't check that the address type matches
Wasm table linking checked type, size, and max — everything but the address width.
Component: JSC WebAssembly | 862994e
WebAssembly's Memory64 proposal lets tables (and memories) be indexed with either i32 or i64 addresses. The JIT and interpreter emit different indexing code depending on which address type a table declares, because address width changes offset computation and bounds checks for call_indirect, table.get/table.set, and similar ops. Import validation is meant to be the boundary that guarantees a module only ever operates on tables matching its statically declared assumptions.
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Table import linking previously validated element type, initial size, and maximum size, but never compared the provided table's addressType() against the module's declared import addressType(). The patch adds that cross-check and throws a LinkError on mismatch, so an i32 table can no longer satisfy a table64 import (or vice versa).
Significance
Without the check, a module compiled to assume 64-bit table indices could be linked against a table object backed by 32-bit indexing internals. Index and bounds-check code generated for one address width would then run against a table laid out for the other — an address-width confusion at the Wasm linking boundary, the type-confusion class applied to table addressing.
Audit directions
- Missing address-type parity on Memory64 import boundaries. This is a validation gap in exactly the place that is supposed to guarantee statically-assumed addressing matches the linked object. The narrow check: confirm memory imports enforce the same
i32-vs-i64address-type parity, since memories have the same Memory64 address-type split; audit the memory-import path alongsideWebAssemblyModuleRecord's table path. In review, any Memory64 import-linking site that validates element type / limits but notaddressType()is the pattern to flag. - Bounds-check width derived from static module info rather than the linked object. Any JIT or interpreter fast path that reads bounds-check or offset width from the module's declared table attributes instead of re-checking the actually-linked table's
addressType()at runtime would still be exposed even with this link-time fix in place — trace thecall_indirect/table.get/table.setcodegen back to where addressing width is chosen. Widest rung: cross-table ops liketable.copy/table.initbetween tables of differing address types imported from different modules — confirm those paths validate address-type compatibility rather than assuming it.