WebAssembly / WebAssembly/wabt

wasm2c linking safety (enforcing import subtyping rules at compile time)

Open
#1,908 9 comments 0 reactions 0 assignees View on GitHub

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 .c file defines the actual pointer, as well as the actual (static) element itself. At runtime, the generated init_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:
  1. wasm2c stops making declarations for imports in the generated .h file. Declarations would be made by the exporting module only. For an import, the module's generated .h file would #include the .h file of every module it imports from. The wasm2c command-line interface would require the user to specify the .h filename for each imported-from module. (I'm a little scared of having a default here because it seems dangerous to write a #include based on a modname that comes from the import component of a possibly adversarial wasm input.)
  2. For the importing module, wasm2c generates a bunch of C11 _Static_assert statements 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.