Skip to content

[wasi-interp] Fix out-of-bounds read tracing guest strings - #2891

Open
Kayyo321 wants to merge 2 commits into
WebAssembly:mainfrom
Kayyo321:fix/wasi-trace-oob-read
Open

Kayyo321 wants to merge 2 commits into
WebAssembly:mainfrom
Kayyo321:fix/wasi-trace-oob-read

Conversation

@Kayyo321

Copy link
Copy Markdown

Fixes #2890.

The WASI trace lines in path_open, path_filestat_get, path_symlink, path_unlink_file, and fd_prestat_dir_name print guest strings with %s. Those strings are length-delimited and need not be NUL-terminated, so a string that ends at the last byte of guest memory is read past the buffer. Each string now prints with %.*s and the length that getMemPtr already validated, clamped to INT_MAX.

The second commit changes path_open's fs_rights_base and fs_rights_inheriting reads from Get<u32>() to Get<u64>(). The WASI ABI declares both as i64. Debug builds asserted on the mismatch before tracing, so the new tests cannot run in Debug without it.

The four tests in test/wasi/trace-strings-*.txt run with --trace. On main, end-memory and zero abort under ASan, and bounded prints abcEXTRA. embedded-nul passes on both trees. It guards the NUL behavior that this change keeps. The expected output of zero ends some lines in a space, because an empty string prints nothing after path_open : .

Tested:

  • WITH_WASI=ON, USE_ASAN=ON, clang, RelWithDebInfo and Debug: python3 test/run-tests.py --bindir <dir> wasi passes 9/9.
  • main, same configurations: the four new tests fail as described above.
  • Default Debug build with BUILD_TESTS=ON: wabt-unittests 138/138. run-tests.py 2008 pass, 0 fail, 522 skipped, with per-test results identical to main.
  • clang-format reports lines 622–626 of interp-wasi.cc. Those lines already fail on main and this change does not touch them.

The new tests do not run in upstream CI, which never builds WITH_WASI. Run them with python3 test/run-tests.py --bindir <dir> wasi on a WITH_WASI build.

Kayyo added 2 commits October 20, 2026 12:22
WASI passes paths and other strings as a pointer and a length, and the
guest does not have to NUL-terminate them. The trace lines in path_open,
path_filestat_get, path_symlink, path_unlink_file, and
fd_prestat_dir_name printed these with %s, so tracing a string that ends
at the last byte of guest memory read past the buffer. Print each string
with %.*s using the length that getMemPtr has already validated, clamped
to INT_MAX.

Add four spec tests under test/wasi that run with --trace. They cover
strings that end at the last byte of memory, empty strings, and an
embedded NUL. Three of them fail on the previous code. The embedded-nul
test checks the NUL behavior that the fix keeps. Run them with
python3 test/run-tests.py --bindir <dir> wasi on a WITH_WASI build.
path_open takes fs_rights_base and fs_rights_inheriting as i64 in the
WASI ABI, but the interpreter read them with Get<u32>(). Debug builds
asserted on the type mismatch under --trace, before any output was
printed. Release builds read only the low 32 bits. Read both with
Get<u64>().

This branch has not been deployed

No deployments
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.

wasi-interp: --trace reads past end of guest strings (heap-buffer-overflow)

1 participant