Skip to content

Validate WASI import arity before binding host functions - #2853

Open
aizu-m wants to merge 1 commit into
WebAssembly:mainfrom
aizu-m:wasi-import-arity
Open

aizu-m wants to merge 1 commit into
WebAssembly:mainfrom
aizu-m:wasi-import-arity

Conversation

@aizu-m

@aizu-m aizu-m commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

ASan on wasm-interp --wasi, running a valid module that under-declares a WASI import:

ERROR: AddressSanitizer: heap-buffer-overflow ... READ of size 8
  #1 wabt::interp::Value::CheckType(wabt::Type) const          interp.h:596
  #2 unsigned long long wabt::interp::Value::Get<...>() const  interp-inl.h:457
  #3 (anon)::WasiInstance::clock_time_get(...)                 interp-wasi.cc:198
  #4 (anon)::clock_time_get(...)                               wasi_api.def:26
  ...
  #13 wabt::interp::Thread::DoCall(...)                        interp.cc:2209
  #19 wabt::interp::WasiRunStart(...)                          interp-wasi.cc:750

Found this fuzzing wasm-interp --wasi with hand-built modules.

WasiBindImports binds each import to its host callback by name and keeps the
func type the module declared. There is a // TODO(sbc): Validate signatures
right next to it. Thread::DoCall then sizes the params/results vectors
from that declared type, but every callback indexes params[]/results[] by
the arity of the real WASI function.

So a module that imports clock_time_get as (i32) -> i32 instead of
(i32 i64 i32) -> i32 still validates, and the call reads params[1] past a
one-element vector. The *_get handlers also do results[0].Set<...>() on an
empty results, so a mis-declared result count is an out-of-bounds write as
well. Both are reachable from an untrusted module through wasm-interp --wasi.

Fix carries each function's (num_params, num_results) in wasi_api.def and
rejects a mismatched import before HostFunc::New, so the arity check fails at
bind time rather than at the out-of-bounds access. Arity only, deliberately:
some callbacks read i64 params as u32 (path_open rights, fd_seek offset),
so checking the types here would reject conforming modules. The declared arity
is fixed by the WASI ABI, so valid modules are unaffected.

Test declares clock_time_get with the wrong arity and expects the bind-time
rejection; the existing test/wasi cases still pass. wasm-interp --wasi
needs -DWITH_WASI=ON.

@zherczeg

Copy link
Copy Markdown
Collaborator

In #2842, it was recommended to remove the entire wasi support form wabt. The 0.1 is outdated, and newer ones require component support (#2695).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants