From c7413154e1bfef6ec75157c589db0303e75bec30 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Thu, 20 Jun 2024 17:21:19 +0800 Subject: [PATCH] Fix ICE caused by seeking past `i64::MAX` --- src/tools/miri/src/shims/unix/fs.rs | 9 +++++++- .../miri/tests/pass/issues/issue-miri-3680.rs | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/issues/issue-miri-3680.rs diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 262e71756c64..e34aa5c09dfe 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -395,7 +395,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Isolation check is done via `FileDescriptor` trait. let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { - SeekFrom::Start(u64::try_from(offset).unwrap()) + if offset < 0 { + // Negative offsets return `EINVAL`. + let einval = this.eval_libc("EINVAL"); + this.set_last_error(einval)?; + return Ok(Scalar::from_i64(-1)); + } else { + SeekFrom::Start(u64::try_from(offset).unwrap()) + } } else if whence == this.eval_libc_i32("SEEK_CUR") { SeekFrom::Current(i64::try_from(offset).unwrap()) } else if whence == this.eval_libc_i32("SEEK_END") { diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3680.rs b/src/tools/miri/tests/pass/issues/issue-miri-3680.rs new file mode 100644 index 000000000000..55b896c91adb --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-3680.rs @@ -0,0 +1,21 @@ +//@ignore-target-windows: File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation + +use std::fs::remove_file; +use std::io::{ErrorKind, Seek}; + +#[path = "../../utils/mod.rs"] +mod utils; + +fn main() { + let path = utils::prepare("miri_test_fs_seek_i64_max_plus_1.txt"); + + let mut f = std::fs::File::create(&path).unwrap(); + let error = f.seek(std::io::SeekFrom::Start(i64::MAX as u64 + 1)).unwrap_err(); + + // It should be error due to negative offset. + assert_eq!(error.kind(), ErrorKind::InvalidInput); + + // Cleanup + remove_file(&path).unwrap(); +}