Skip to content

Commit 67a63f8

Browse files
committed
Auto merge of #1056 - RalfJung:max, r=RalfJung
use new isize_max method in FS accesses also check full buffers for validity
2 parents 9f1aec3 + 5345636 commit 67a63f8

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

src/shims/fs.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::convert::TryFrom;
33
use std::fs::{remove_file, File, OpenOptions};
44
use std::io::{Read, Write};
55

6-
use rustc::ty::layout::Size;
6+
use rustc::ty::layout::{Size, Align};
77

88
use crate::stacked_borrows::Tag;
99
use crate::*;
@@ -166,18 +166,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
166166

167167
this.check_no_isolation("read")?;
168168

169-
let ptr_size = this.pointer_size().bits();
170-
171-
// We cap the number of read bytes to the largest value that we are able to fit in both the
172-
// host's and target's `isize`.
169+
let fd = this.read_scalar(fd_op)?.to_i32()?;
170+
let buf = this.read_scalar(buf_op)?.not_undef()?;
173171
let count = this
174172
.read_scalar(count_op)?
175-
.to_machine_usize(&*this.tcx)?
176-
.min((1 << (ptr_size - 1)) - 1) // max value of target `isize`
177-
.min(isize::max_value() as u64);
173+
.to_machine_usize(&*this.tcx)?;
178174

179-
let fd = this.read_scalar(fd_op)?.to_i32()?;
180-
let buf = this.read_scalar(buf_op)?.not_undef()?;
175+
// Check that the *entire* buffer is actually valid memory.
176+
this.memory.check_ptr_access(buf, Size::from_bytes(count), Align::from_bytes(1).unwrap())?;
177+
178+
// We cap the number of read bytes to the largest value that we are able to fit in both the
179+
// host's and target's `isize`. This saves us from having to handle overflows later.
180+
let count = count
181+
.min(this.isize_max() as u64)
182+
.min(isize::max_value() as u64);
181183

182184
if let Some(handle) = this.machine.file_handler.handles.get_mut(&fd) {
183185
// This can never fail because `count` was capped to be smaller than
@@ -219,18 +221,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
219221

220222
this.check_no_isolation("write")?;
221223

222-
let ptr_size = this.pointer_size().bits();
223-
224-
// We cap the number of read bytes to the largest value that we are able to fit in both the
225-
// host's and target's `isize`.
224+
let fd = this.read_scalar(fd_op)?.to_i32()?;
225+
let buf = this.read_scalar(buf_op)?.not_undef()?;
226226
let count = this
227227
.read_scalar(count_op)?
228-
.to_machine_usize(&*this.tcx)?
229-
.min((1 << (ptr_size - 1)) - 1) // max value of target `isize`
230-
.min(isize::max_value() as u64);
228+
.to_machine_usize(&*this.tcx)?;
231229

232-
let fd = this.read_scalar(fd_op)?.to_i32()?;
233-
let buf = this.read_scalar(buf_op)?.not_undef()?;
230+
// Check that the *entire* buffer is actually valid memory.
231+
this.memory.check_ptr_access(buf, Size::from_bytes(count), Align::from_bytes(1).unwrap())?;
232+
233+
// We cap the number of written bytes to the largest value that we are able to fit in both the
234+
// host's and target's `isize`. This saves us from having to handle overflows later.
235+
let count = count
236+
.min(this.isize_max() as u64)
237+
.min(isize::max_value() as u64);
234238

235239
if let Some(handle) = this.machine.file_handler.handles.get_mut(&fd) {
236240
let bytes = this.memory.read_bytes(buf, Size::from_bytes(count))?;

0 commit comments

Comments
 (0)