Skip to content

Bitcasts from extern symbols to function pointers produce corrupted WebAssembly binary #60003

Closed
@RReverser

Description

@RReverser

Original issue in emscripten-core/emscripten#15722 / rust-lang/rust#91628.

The minimal repro for C/C++ looks like this:

extern char maybe_func;

int main() {
    int(*func)() = (int(*)())&maybe_func;
    return func();
}

This produces the following LLVM IR with -target wasm32-unknown-emscripten (but likely reproducible with other Wasm targets too):

@maybe_func = external local_unnamed_addr global i8, align 1

define hidden noundef i32 @__main_argc_argv(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr #0 {
  %3 = tail call noundef i32 @maybe_func()
  ret i32 %3
}

attributes #0 = { mustprogress norecurse "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" }

The Wasm generated by LLVM is corrupted, and wasm-opt, wasm-validate etc fail:

$ emcc temp.c -O -Wl,--allow-undefined
[parse exception: attempted pop from empty stack / beyond block start boundary at 262 (at 0:262)]
Fatal: error in parsing input
emcc: error: '/home/rreverser/emsdk/upstream/bin/wasm-emscripten-finalize --dyncalls-i64 --pass-arg=legalize-js-interface-exported-helpers a.out.wasm -o a.out.wasm --detect-features' failed (returned 1)

As discussed in linked issues, this is likely due to maybe_func being called directly without bitcast handling that Wasm function pointers require. IIUC this is not possible to solve in general for arbitrary casts, but should be doable for extern symbols.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions