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))
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| {
// 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.
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());