Skip to content

Commit 9463c16

Browse files
committed
Fix dangling pointer bug for zero-sized reads
1 parent 78e0d30 commit 9463c16

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

src/shims/io.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
156156
// Remove the file handle to avoid borrowing issues
157157
this.remove_handle_and(fd, |mut handle, this| {
158158
// Don't use `?` to avoid returning before reinserting the handle
159-
let bytes = this
160-
.memory_mut()
161-
.get_mut(buf.alloc_id).and_then(|alloc|
162-
alloc.get_bytes_mut(tcx, buf, Size::from_bytes(count))
163-
.map(|buffer| handle.file.read(buffer).map(|bytes| bytes as i64))
164-
);
159+
160+
let bytes = this.memory_mut().get_mut(buf.alloc_id).and_then(|alloc| {
161+
if count != 0 {
162+
alloc
163+
.get_bytes_mut(tcx, buf, Size::from_bytes(count))
164+
.map(|buffer| handle.file.read(buffer))
165+
} else {
166+
// Using `Allocation::get_bytes_mut` requires to actually put data into
167+
// the allocation even if we take 0 bytes of it. In that case we use an
168+
// empty buffer instead to avoid dangling pointers.
169+
let mut empty = Vec::new();
170+
let result = Ok(handle.file.read(empty.as_mut_slice()));
171+
assert!(empty.is_empty());
172+
result
173+
}
174+
});
165175
// Reinsert the file handle
166176
this.machine.file_handler.handles.insert(fd, handle);
167-
this.consume_result(bytes?)
177+
this.consume_result(bytes?.map(|bytes| bytes as i64))
168178
})
169179
}
170180

tests/run-pass/file_read.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@ use std::fs::File;
55
use std::io::{ Read, Write };
66

77
fn main() {
8-
// FIXME: remove the file and delete it when `rm` is implemented.
8+
// FIXME: Remove the file when the required shims are implemented
9+
let path = "./tests/hello.txt";
10+
let bytes = b"Hello, World!\n";
911

1012
// Test creating, writing and closing a file (closing is tested when `file` is dropped).
11-
let mut file = File::create("./tests/hello.txt").unwrap();
12-
file.write(b"Hello, World!\n").unwrap();
13+
let mut file = File::create(path).unwrap();
14+
file.write(bytes).unwrap();
1315

1416
// Test opening, reading and closing a file.
15-
let mut file = File::open("./tests/hello.txt").unwrap();
16-
let mut contents = String::new();
17-
file.read_to_string(&mut contents).unwrap();
18-
assert_eq!("Hello, World!\n", contents);
17+
let mut file = File::open(path).unwrap();
18+
let mut contents = Vec::new();
19+
file.read(&mut contents).unwrap();
20+
assert_eq!(bytes, contents.as_slice());
1921
}

0 commit comments

Comments
 (0)