Skip to content

Commit 5a9f3e0

Browse files
committed
Return earlier when reading/writing 0 bytes
1 parent f5022b1 commit 5a9f3e0

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

src/shims/io.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -149,25 +149,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
149149

150150
let tcx = &{ this.tcx.tcx };
151151

152+
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
153+
// Reading zero bytes should not change `buf`
154+
if count == 0 {
155+
return Ok(0);
156+
}
152157
let fd = this.read_scalar(fd_op)?.to_i32()?;
153158
let buf_scalar = this.read_scalar(buf_op)?.not_undef()?;
154-
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
155159

156160
// Remove the file handle to avoid borrowing issues
157161
this.remove_handle_and(fd, |mut handle, this| {
158162
// Don't use `?` to avoid returning before reinserting the handle
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))
163+
let bytes = this.force_ptr(buf_scalar).and_then(|buf| {
164+
this.memory_mut().get_mut(buf.alloc_id).and_then(|alloc| {
165+
alloc
166+
.get_bytes_mut(tcx, buf, Size::from_bytes(count))
167167
.map(|buffer| handle.file.read(buffer))
168-
))
169-
170-
};
168+
})
169+
});
171170
// Reinsert the file handle
172171
this.machine.file_handler.handles.insert(fd, handle);
173172
this.consume_result(bytes?.map(|bytes| bytes as i64))
@@ -188,9 +187,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
188187

189188
let tcx = &{ this.tcx.tcx };
190189

190+
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
191+
// Reading zero bytes should not change `buf`
192+
if count == 0 {
193+
return Ok(0);
194+
}
191195
let fd = this.read_scalar(fd_op)?.to_i32()?;
192196
let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
193-
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
194197

195198
this.remove_handle_and(fd, |mut handle, this| {
196199
let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| {

tests/run-pass/file_read.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// compile-flags: -Zmiri-disable-isolation
33

44
use std::fs::File;
5-
use std::io::{ Read, Write };
5+
use std::io::{Read, Write};
66

77
fn main() {
88
// FIXME: remove the file and delete it when `rm` is implemented.
@@ -14,9 +14,8 @@ fn main() {
1414
// Test opening, reading and closing a file.
1515
let mut file = File::open(path).unwrap();
1616
let mut contents = Vec::new();
17-
// Reading 0 bytes should not fill `contents`.
18-
file.read(&mut contents).unwrap();
19-
assert!(contents.is_empty());
17+
// Reading 0 bytes should not move the file pointer.
18+
file.read(&mut []).unwrap();
2019
// Reading until EOF should get the whole text.
2120
file.read_to_end(&mut contents).unwrap();
2221
assert_eq!(bytes, contents.as_slice());

0 commit comments

Comments
 (0)