Skip to content

Commit 78e0d30

Browse files
committed
Avoid early return after handles are removed
1 parent 5a05c04 commit 78e0d30

File tree

1 file changed

+27
-28
lines changed

1 file changed

+27
-28
lines changed

src/shims/io.rs

Lines changed: 27 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,18 @@ 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).and_then(|alloc|
162+
alloc.get_bytes_mut(tcx, buf, Size::from_bytes(count))
163+
.map(|buffer| handle.file.read(buffer).map(|bytes| bytes as i64))
164+
);
165+
// Reinsert the file handle
166+
this.machine.file_handler.handles.insert(fd, handle);
167+
this.consume_result(bytes?)
168+
})
174169
}
175170

176171
fn write(
@@ -191,13 +186,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191186
let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
192187
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
193188

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-
197189
this.remove_handle_and(fd, |mut handle, this| {
198-
let bytes = handle.file.write(&bytes).map(|bytes| bytes as i64);
190+
let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| {
191+
alloc
192+
.get_bytes(tcx, buf, Size::from_bytes(count))
193+
.map(|bytes| handle.file.write(bytes).map(|bytes| bytes as i64))
194+
});
199195
this.machine.file_handler.handles.insert(fd, handle);
200-
this.consume_result(bytes)
196+
this.consume_result(bytes?)
201197
})
202198
}
203199

@@ -251,7 +247,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251247
///
252248
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
253249
/// 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> {
250+
fn consume_result<T: From<i32>>(
251+
&mut self,
252+
result: std::io::Result<T>,
253+
) -> InterpResult<'tcx, T> {
255254
match result {
256255
Ok(ok) => Ok(ok),
257256
Err(e) => {

0 commit comments

Comments
 (0)