Skip to content

Commit 83e5ded

Browse files
committed
Avoid early return after handles are removed
1 parent 5a05c04 commit 83e5ded

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

src/shims/io.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
2-
use std::fs::{ File, OpenOptions };
3-
use std::io::{ Read, Write };
2+
use std::fs::{File, OpenOptions};
3+
use std::io::{Read, Write};
44

55
use rustc::ty::layout::Size;
66

@@ -130,10 +130,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
130130

131131
let fd = this.read_scalar(fd_op)?.to_i32()?;
132132

133-
this.remove_handle_and(
134-
fd,
135-
|handle, this| this.consume_result(handle.file.sync_all().map(|_| 0i32)),
136-
)
133+
this.remove_handle_and(fd, |handle, this| {
134+
this.consume_result(handle.file.sync_all().map(|_| 0i32))
135+
})
137136
}
138137

139138
fn read(
@@ -155,22 +154,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
155154
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
156155

157156
// Remove the file handle to avoid borrowing issues
158-
this.remove_handle_and(
159-
fd,
160-
|mut handle, this| {
161-
let bytes = handle
162-
.file
163-
.read(this.memory_mut().get_mut(buf.alloc_id)?.get_bytes_mut(
164-
tcx,
165-
buf,
166-
Size::from_bytes(count),
167-
)?)
168-
.map(|bytes| bytes as i64);
169-
// Reinsert the file handle
170-
this.machine.file_handler.handles.insert(fd, handle);
171-
this.consume_result(bytes)
172-
},
173-
)
157+
this.remove_handle_and(fd, |mut handle, this| {
158+
// Don't use `?` to avoid returning before reinserting the handle
159+
let bytes = this
160+
.memory_mut()
161+
.get_mut(buf.alloc_id)?
162+
.get_bytes_mut(tcx, buf, Size::from_bytes(count))
163+
.map(|buffer| handle.file.read(buffer).map(|bytes| bytes as i64));
164+
// Reinsert the file handle
165+
this.machine.file_handler.handles.insert(fd, handle);
166+
this.consume_result(bytes?)
167+
})
174168
}
175169

176170
fn write(
@@ -191,13 +185,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191185
let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
192186
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
193187

194-
// `to_vec` is needed to avoid borrowing issues when writing to the file.
195-
let bytes = this.memory().get(buf.alloc_id)?.get_bytes(tcx, buf, Size::from_bytes(count))?.to_vec();
196-
197188
this.remove_handle_and(fd, |mut handle, this| {
198-
let bytes = handle.file.write(&bytes).map(|bytes| bytes as i64);
189+
let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| {
190+
alloc
191+
.get_bytes(tcx, buf, Size::from_bytes(count))
192+
.map(|bytes| handle.file.write(bytes).map(|bytes| bytes as i64))
193+
});
199194
this.machine.file_handler.handles.insert(fd, handle);
200-
this.consume_result(bytes)
195+
this.consume_result(bytes?)
201196
})
202197
}
203198

@@ -251,7 +246,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251246
///
252247
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
253248
/// functions return different integer types (like `read`, that returns an `i64`)
254-
fn consume_result<T: From<i32>>(&mut self, result: std::io::Result<T>) -> InterpResult<'tcx, T> {
249+
fn consume_result<T: From<i32>>(
250+
&mut self,
251+
result: std::io::Result<T>,
252+
) -> InterpResult<'tcx, T> {
255253
match result {
256254
Ok(ok) => Ok(ok),
257255
Err(e) => {

0 commit comments

Comments
 (0)