diff --git a/lib/wasix/src/syscalls/wasi/fd_seek.rs b/lib/wasix/src/syscalls/wasi/fd_seek.rs index 395c8718768..65d60514933 100644 --- a/lib/wasix/src/syscalls/wasi/fd_seek.rs +++ b/lib/wasix/src/syscalls/wasi/fd_seek.rs @@ -75,8 +75,12 @@ pub(crate) fn fd_seek_internal( fd_entry.offset.fetch_add(offset, Ordering::AcqRel) + offset } else if offset < 0 { let offset = offset.unsigned_abs(); - // FIXME: need to handle underflow! - fd_entry.offset.fetch_sub(offset, Ordering::AcqRel) - offset + + wasi_try_ok_ok!(fd_entry + .offset + .fetch_sub(offset, Ordering::AcqRel) + .checked_sub(offset) + .ok_or(Errno::Inval)) } else { fd_entry.offset.load(Ordering::Acquire) } diff --git a/tests/wasi-fyi/fd_seek_cur_negative_underflow.rs b/tests/wasi-fyi/fd_seek_cur_negative_underflow.rs new file mode 100644 index 00000000000..e961c9ad6bb --- /dev/null +++ b/tests/wasi-fyi/fd_seek_cur_negative_underflow.rs @@ -0,0 +1,32 @@ +use std::os::fd::AsRawFd; + +#[link(wasm_import_module = "wasi_snapshot_preview1")] +extern "C" { + pub fn fd_seek(fd: i32, offset: i64, whence: i32, filesize: i32) -> i32; +} + +const ERRNO_INVAL: i32 = 28; + +const WHENCE_CUR: i32 = 1; + +fn main() { + unsafe { + let large_negative_offset = -6551085931117533355; + let mut filesize = 0u64; + + let f = std::fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open("test.sh") + .unwrap(); + let errno = fd_seek( + f.as_raw_fd(), + large_negative_offset, + WHENCE_CUR, + &mut filesize as *mut u64 as usize as i32, + ); + + assert_eq!(errno, ERRNO_INVAL); + } +}