Skip to content

Commit efbe798

Browse files
committed
Avoid buffer allocation to read files
1 parent 775246e commit efbe798

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

src/shims/io.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::collections::HashMap;
22
use std::fs::File;
33
use std::io::Read;
44

5+
use rustc::ty::layout::Size;
6+
57
use crate::stacked_borrows::Tag;
68
use crate::*;
79

@@ -53,7 +55,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5355
let fd = File::open(&path).map(|file| {
5456
let mut fh = &mut this.machine.file_handler;
5557
fh.low += 1;
56-
fh.handles.insert(fh.low, FileHandle{ file, flag});
58+
fh.handles.insert(fh.low, FileHandle { file, flag });
5759
fh.low
5860
});
5961

@@ -81,7 +83,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
8183
let flag = this.read_scalar(arg_op.unwrap())?.to_i32()?;
8284
// The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
8385
let fd_cloexec = this.eval_libc_i32("FD_CLOEXEC")?;
84-
if let Some(FileHandle{ flag: old_flag, .. }) = this.machine.file_handler.handles.get_mut(&fd) {
86+
if let Some(FileHandle { flag: old_flag, .. }) =
87+
this.machine.file_handler.handles.get_mut(&fd)
88+
{
8589
if flag ^ *old_flag == fd_cloexec {
8690
*old_flag = flag;
8791
} else {
@@ -136,23 +140,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
136140
let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
137141
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
138142

139-
let mut bytes = vec![0; count as usize];
140-
141-
let read_result = if let Some(FileHandle { file, ..}) = this.machine.file_handler.handles.get_mut(&fd) {
142-
file.read(&mut bytes).map(|bytes| bytes as i64)
143+
// Remove the file handle to avoid borrowing issues
144+
if let Some(mut handle) = this.machine.file_handler.handles.remove(&fd) {
145+
let bytes = handle
146+
.file
147+
.read(this.memory_mut().get_mut(buf.alloc_id)?.get_bytes_mut(
148+
tcx,
149+
buf,
150+
Size::from_bytes(count),
151+
)?)
152+
.map(|bytes| bytes as i64);
153+
// Reinsert the file handle
154+
this.machine.file_handler.handles.insert(fd, handle);
155+
this.consume_result::<i64>(bytes, -1)
143156
} else {
144157
this.machine.last_error = this.eval_libc_i32("EBADF")? as u32;
145-
return Ok(-1);
146-
};
147-
148-
let read_bytes = this.consume_result::<i64>(read_result, -1)?;
149-
if read_bytes != -1 {
150-
bytes.truncate(read_bytes as usize);
151-
this.memory_mut()
152-
.get_mut(buf.alloc_id)?
153-
.write_bytes(tcx, buf, &bytes)?;
158+
Ok(-1)
154159
}
155-
Ok(read_bytes)
156160
}
157161

158162
fn consume_result<T>(&mut self, result: std::io::Result<T>, t: T) -> InterpResult<'tcx, T> {

0 commit comments

Comments
 (0)