about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdwin White <adwinw01@gmail.com>2024-06-20 17:21:19 +0800
committerAdwin White <adwinw01@gmail.com>2024-06-20 23:38:00 +0800
commitc7413154e1bfef6ec75157c589db0303e75bec30 (patch)
treeee9d1ae46762a6864cbf507d5e90c304bb87d5dd
parent66ad792c4ef99dd9e3d3e5303eaaeec867857cae (diff)
downloadrust-c7413154e1bfef6ec75157c589db0303e75bec30.tar.gz
rust-c7413154e1bfef6ec75157c589db0303e75bec30.zip
Fix ICE caused by seeking past `i64::MAX`
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs9
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-3680.rs21
2 files changed, 29 insertions, 1 deletions
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 262e71756c6..e34aa5c09df 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 00000000000..55b896c91ad
--- /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();
+}