From 6c36a8c949a3e506b48481d746df85e6596d097d Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 2 Oct 2019 08:50:32 -0500 Subject: [PATCH] Return earlier when reading/writing 0 bytes --- src/shims/io.rs | 30 ++++++++++++++++-------------- tests/run-pass/file_read.rs | 10 ++++++---- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/shims/io.rs b/src/shims/io.rs index 9d3e3d26162..74b8dde5c7f 100644 --- a/src/shims/io.rs +++ b/src/shims/io.rs @@ -149,25 +149,23 @@ fn read( let tcx = &{ this.tcx.tcx }; + let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?; + // Reading zero bytes should not change `buf` + if count == 0 { + return Ok(0); + } let fd = this.read_scalar(fd_op)?.to_i32()?; let buf_scalar = this.read_scalar(buf_op)?.not_undef()?; - let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?; // Remove the file handle to avoid borrowing issues this.remove_handle_and(fd, |mut handle, this| { // Don't use `?` to avoid returning before reinserting the handle - let bytes = - if count == 0 { - Ok(handle.file.read(&mut [])) - } else { - this.force_ptr(buf_scalar).and_then(|buf| this - .memory_mut() - .get_mut(buf.alloc_id).and_then(|alloc| - alloc.get_bytes_mut(tcx, buf, Size::from_bytes(count)) - .map(|buffer| handle.file.read(buffer)) - )) - - }; + let bytes = this.force_ptr(buf_scalar).and_then(|buf| { + this.memory_mut() + .get_mut(buf.alloc_id)? + .get_bytes_mut(tcx, buf, Size::from_bytes(count)) + .map(|buffer| handle.file.read(buffer)) + }); // Reinsert the file handle this.machine.file_handler.handles.insert(fd, handle); this.consume_result(bytes?.map(|bytes| bytes as i64)) @@ -188,9 +186,13 @@ fn write( let tcx = &{ this.tcx.tcx }; + let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?; + // Writing zero bytes should not change `buf` + if count == 0 { + return Ok(0); + } let fd = this.read_scalar(fd_op)?.to_i32()?; let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?; - let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?; this.remove_handle_and(fd, |mut handle, this| { let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| { diff --git a/tests/run-pass/file_read.rs b/tests/run-pass/file_read.rs index a17f948980a..666abd65c12 100644 --- a/tests/run-pass/file_read.rs +++ b/tests/run-pass/file_read.rs @@ -2,7 +2,7 @@ // compile-flags: -Zmiri-disable-isolation use std::fs::File; -use std::io::{ Read, Write }; +use std::io::{Read, Write}; fn main() { // FIXME: remove the file and delete it when `rm` is implemented. @@ -10,13 +10,15 @@ fn main() { let bytes = b"Hello, World!\n"; // Test creating, writing and closing a file (closing is tested when `file` is dropped). let mut file = File::create(path).unwrap(); + // Writing 0 bytes should not change the file contents. + file.write(&mut []).unwrap(); + file.write(bytes).unwrap(); // Test opening, reading and closing a file. let mut file = File::open(path).unwrap(); let mut contents = Vec::new(); - // Reading 0 bytes should not fill `contents`. - file.read(&mut contents).unwrap(); - assert!(contents.is_empty()); + // Reading 0 bytes should not move the file pointer. + file.read(&mut []).unwrap(); // Reading until EOF should get the whole text. file.read_to_end(&mut contents).unwrap(); assert_eq!(bytes, contents.as_slice()); -- 2.44.0