Skip to content

Commit f5022b1

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

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

src/shims/io.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,21 +150,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
150150
let tcx = &{ this.tcx.tcx };
151151

152152
let fd = this.read_scalar(fd_op)?.to_i32()?;
153-
let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
153+
let buf_scalar = this.read_scalar(buf_op)?.not_undef()?;
154154
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
155155

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+
let bytes =
160+
if count == 0 {
161+
Ok(handle.file.read(&mut []))
162+
} else {
163+
this.force_ptr(buf_scalar).and_then(|buf| this
164+
.memory_mut()
165+
.get_mut(buf.alloc_id).and_then(|alloc|
166+
alloc.get_bytes_mut(tcx, buf, Size::from_bytes(count))
167+
.map(|buffer| handle.file.read(buffer))
168+
))
169+
170+
};
165171
// Reinsert the file handle
166172
this.machine.file_handler.handles.insert(fd, handle);
167-
this.consume_result(bytes?)
173+
this.consume_result(bytes?.map(|bytes| bytes as i64))
168174
})
169175
}
170176

tests/run-pass/file_read.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@ use std::io::{ Read, Write };
66

77
fn main() {
88
// FIXME: remove the file and delete it when `rm` is implemented.
9-
9+
let path = "./tests/hello.txt";
10+
let bytes = b"Hello, World!\n";
1011
// 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-
12+
let mut file = File::create(path).unwrap();
13+
file.write(bytes).unwrap();
1414
// 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);
15+
let mut file = File::open(path).unwrap();
16+
let mut contents = Vec::new();
17+
// Reading 0 bytes should not fill `contents`.
18+
file.read(&mut contents).unwrap();
19+
assert!(contents.is_empty());
20+
// Reading until EOF should get the whole text.
21+
file.read_to_end(&mut contents).unwrap();
22+
assert_eq!(bytes, contents.as_slice());
1923
}

0 commit comments

Comments
 (0)