Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasi fd_read sets bogous n_bytes_read value / ignores buffer length on webassembly.sh #112

Open
jcaesar opened this issue May 25, 2022 · 2 comments
Labels

Comments

@jcaesar
Copy link

jcaesar commented May 25, 2022

The following Rust code panics in webassembly.sh when compiled with rustc ≥ 1.57 (but runs fine on desktop wasmer).

use std::io::Read;
fn main() {
    let mut buffer = String::new();
    std::io::stdin().read_to_string(&mut buffer).unwrap();
}

Panic

thread 'main' panicked at 'assertion failed: n <= buf.len()', library/std/src/io/mod.rs:398:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Quick repro:

  • open
  • enter echo putatleastthirtytwobyteshereandyouwillsee | ./repro

The failing assert is here. I haven't really looked at how the surrounding code changed, but change it did.

Adding some more debug output to wasi, I get the following with 1.56 on desktop

[1653482124.970 DEBUG wasmer_wasi::state] Initializing WASI filesystem
[1653482124.972 DEBUG wasmer_wasi::syscalls] wasi::environ_sizes_get
[1653482124.972 DEBUG wasmer_wasi::syscalls] env_var_count: 0, env_buf_size: 0
[1653482124.972 DEBUG wasmer_wasi::syscalls] wasi::fd_read: fd=0
[1653482124.972 DEBUG wasmer_wasi::syscalls] wasi::read_bytes: buf=0x00102910 buf_len=8192 bytes_read=42
[1653482124.972 DEBUG wasmer_wasi::syscalls] wasi::fd_read: fd=0
[1653482124.973 DEBUG wasmer_wasi::syscalls] wasi::read_bytes: buf=0x00102910 buf_len=8192 bytes_read=0

and the following on 1.57

[1653482131.932 DEBUG wasmer_wasi::state] Initializing WASI filesystem
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::environ_sizes_get
[1653482131.934 DEBUG wasmer_wasi::syscalls] env_var_count: 0, env_buf_size: 0
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::fd_read: fd=0
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::read_bytes: buf=0x001048b0 buf_len=32 bytes_read=32
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::fd_read: fd=0
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::read_bytes: buf=0x001048d0 buf_len=32 bytes_read=10
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::fd_read: fd=0
[1653482131.934 DEBUG wasmer_wasi::syscalls] wasi::read_bytes: buf=0x001048da buf_len=22 bytes_read=0

so I guess the initial buffer size changed and webassembly.sh somehow manages to return the wrong value for bytes_read (maybe 42?).

@jcaesar jcaesar changed the title Incompatibility between webassembly.sh and rust 1.57 read_to_end: Incompatibility between webassembly.sh and rust 1.57 May 25, 2022
@jcaesar
Copy link
Author

jcaesar commented May 27, 2022

Actually, nevermind this being about rust ≥1.57, this occurs with all rust versions for large enough inputs:

$ curl https://gist.githubusercontent.com/jcaesar/c33e0759fc120cfe964a16e0b3783379/raw/4d67aafbaaa9cccf4dc274b9934cf84b6bab25c7/1.56.wasm -o repro
$ sl-cmd '"asdf"*3000' | ./repro
thread 'main' panicked at 'range end index 12003 out of range for slice of length 8192', library/std/src/io/buffered/bufreader.rs:325:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

This is also happening with other languages/compilers/system libs, they just have less strict checks and probably do some undefined behavior memory access… Nice.

$ sl-cmd '"asdf"*3000' | hexdump -C
00000000  22 61 73 64 66 61 73 64  66 61 73 64 66 61 73 00  |"asdfasdfasdfas.|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000410  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 2a  |...............*|
00000420  30 30 30 30 34 31 30 20  20 30 30 20 30 30 20 30  |0000410  00 00 0|
00000430  30 20 33 30 20 33 34 20  33 31 20 33 30 20 32 30  |0 30 34 31 30 20|
00000440  20 20 33 33 20 33 31 20  32 30 20 33 33 20 33 30  |  33 31 20 33 30|
00000450  20 32 30 20 33 33 20 33  30 20 20 7c 20 20 33 33  | 20 33 30  |  33|
00000460  33 33 20 33 30 20 20 7c  20 20 33 33 00 00 00 00  |33 30  |  33....|
00000470  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000820  00 00 00 00 00 00 00 43  2e 55 54 46 2d 38 3b 43  |.......C.UTF-8;C|
00000830  3b 43 3b 43 3b 43 3b 43  00 00 00 00 00 00 00 00  |;C;C;C;C........|
00000840  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

@jcaesar jcaesar changed the title read_to_end: Incompatibility between webassembly.sh and rust 1.57 wasi fd_read sets bogous n_bytes_read value / ignores buffer length on webassembly.sh May 27, 2022
@jcaesar
Copy link
Author

jcaesar commented May 29, 2022

I made a little test file to check whether a value directly after the buffer is overwritten, i.e. whether the just the returned n_bytes is wrong, or whether it ignores the input length.

Seems only the returned value is wrong, the canary is left intact:

$ curl https://gist.githubusercontent.com/jcaesar/c33e0759fc120cfe964a16e0b3783379/raw/0c44e77e0118ab1e6781e802c377f574da2c907a/test.wasm -o test
$ sl-cmd '"asdf" * 20' | ./test
fd_read: ret 0, nbytes = 83, canary 739477648 = 739477648
fd_read: ret 0, nbytes = 0, canary 739477648 = 739477648
fail = 1

Other than that, this only happens when piping. But I haven't found the code for piping in wasm-terminal, so no idea what's going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant