WebAssembly / WebAssembly/wabt
wasm2c linking safety (enforcing import subtyping rules at compile time)
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 8.1k
- Forks
- 827
- Avg merge
- 4d 6h
- Merged PRs (30d)
- 18
Description
(Spinning this off from https://github.com/WebAssembly/wabt/pull/1814#discussion_r850917266)
Here is a proposal for how to improve safety when linking multiple modules together with wasm2c.
As background:
-
At present, for every import or export, wasm2c writes an extern declaration in the generated header file. The declaration is in the form of a global pointer, named with the module name and import/export name. The exporting module's
.cfile defines the actual pointer, as well as the actual (static) element itself. At runtime, the generatedinit_exports()function initializes each pointers to point to the exported element. -
If #1814 is merged, the behavior remains essentially the same. (The difference is that exports are now represented by functions that take a module instance pointer, instead of with global pointers, but the naming and linking is basically the same.)
The concern in both cases is that, because both imports and exports produce a declaration in the generated .h file, and each module's .c file only includes its own .h file, the compiler won't see an incompatibility between the types of an export vs. import. (It became easier for this to happen after removing signature mangling from function and global imports/exports, but I think this was and still is an issue for memories and tables too.) The C linker will happily link the .o files together as long as the symbol can be resolved.
So it's pretty easy to get in a situation where compiling two wasm2c-generated modules each succeeds independently, and then linking the resulting .o files succeeds, but the user gets invalid behavior at runtime. This seems to violate the Wasm soundness guarantees.
Here's a straw-man proposal that would try to catch these at compile-time instead:
- wasm2c stops making declarations for imports in the generated
.hfile. Declarations would be made by the exporting module only. For an import, the module's generated.hfile would#includethe.hfile of every module it imports from. Thewasm2ccommand-line interface would require the user to specify the.hfilename for each imported-from module. (I'm a little scared of having a default here because it seems dangerous to write a#includebased on a modname that comes from the import component of a possibly adversarial wasm input.) - For the importing module,
wasm2cgenerates a bunch of C11_Static_assertstatements to enforce the Import Subtyping validation rules (https://webassembly.github.io/spec/core/valid/types.html#import-subtyping). Usually these are just about type equality, but for memories and tables it has to compare the min and max sizes. This would mean that compiling a wasm2c-generated module would require a C11 compiler (or there could be a command-line flag to disable them...).
If there is consensus to go in this direction, it would also be nice to prettify the naming of imports and exports. Maybe instead of Z_modnameZ_name, it could be something like w2c_modname_name or wasm_modname_name. (A distinguished prefix seems necessary to avoid letting modules import a system symbol automatically.)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing wasm2c's generated header and source handling for imports and exports, then trace the command-line path that supplies imported-from module headers. Compare the proposed C11 _Static_assert checks with the WebAssembly import subtyping rules. Done means incompatible imports are rejected during compilation rather than only detected at runtime or left to the C linker.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cpp, wasm
- Domain
- compilers, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100