Skip to content

Commit 7f47626

Browse files
committed
Auto merge of #1248 - RalfJung:overflow, r=RalfJung
detect UB: overflow in copy/write_bytes Fixes #1234
2 parents 70ab91d + 238ed49 commit 7f47626

File tree

6 files changed

+42
-6
lines changed

6 files changed

+42
-6
lines changed

miri

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ working directory.
1111
./miri build <flags>:
1212
Just build miri. <flags> are passed to `cargo build`.
1313
14+
./miri check <flags>:
15+
Just check miri. <flags> are passed to `cargo check`.
16+
1417
./miri test <flags>:
1518
Build miri, set up a sysroot and then run the test suite. <flags> are passed
1619
to the final `cargo test` invocation.
@@ -99,6 +102,10 @@ install|install-debug)
99102
# "--offline" to avoid querying the registry (for yanked packages).
100103
exec cargo install $CARGO_INSTALL_FLAGS --path "$(dirname "$0")" --force --locked --offline "$@"
101104
;;
105+
check|check-debug)
106+
# Check, and let caller control flags.
107+
exec cargo check $CARGO_BUILD_FLAGS "$@"
108+
;;
102109
build|build-debug)
103110
# Build, and let caller control flags.
104111
exec cargo build $CARGO_BUILD_FLAGS "$@"

src/shims/intrinsics.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::convert::TryFrom;
44
use rustc::mir;
55
use rustc::mir::interpret::{InterpResult, PointerArithmetic};
66
use rustc::ty;
7-
use rustc::ty::layout::{Align, LayoutOf, Size};
7+
use rustc::ty::layout::{Align, LayoutOf};
88
use rustc_apfloat::Float;
99
use rustc_span::source_map::Span;
1010

@@ -226,11 +226,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
226226
=> {
227227
let elem_ty = substs.type_at(0);
228228
let elem_layout = this.layout_of(elem_ty)?;
229-
let elem_size = elem_layout.size.bytes();
230229
let count = this.read_scalar(args[2])?.to_machine_usize(this)?;
231230
let elem_align = elem_layout.align.abi;
232231

233-
let size = Size::from_bytes(count) * elem_size;
232+
let size = elem_layout.size.checked_mul(count, this)
233+
.ok_or_else(|| err_ub_format!("overflow computing total size of `{}`", intrinsic_name))?;
234234
let src = this.read_scalar(args[0])?.not_undef()?;
235235
let src = this.memory.check_ptr_access(src, size, elem_align)?;
236236
let dest = this.read_scalar(args[1])?.not_undef()?;
@@ -493,7 +493,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
493493
let val_byte = this.read_scalar(args[1])?.to_u8()?;
494494
let ptr = this.read_scalar(args[0])?.not_undef()?;
495495
let count = this.read_scalar(args[2])?.to_machine_usize(this)?;
496-
let byte_count = ty_layout.size * count;
496+
let byte_count = ty_layout.size.checked_mul(count, this)
497+
.ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?;
497498
this.memory
498499
.write_bytes(ptr, iter::repeat(val_byte).take(byte_count.bytes() as usize))?;
499500
}

tests/compile-fail/copy_null.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//error-pattern: invalid use of NULL pointer
21
#![feature(intrinsics)]
32

43
// Directly call intrinsic to avoid debug assertions in libstd
@@ -10,5 +9,5 @@ fn main() {
109
let mut data = [0u16; 4];
1110
let ptr = &mut data[0] as *mut u16;
1211
// Even copying 0 elements from NULL should error.
13-
unsafe { copy_nonoverlapping(std::ptr::null(), ptr, 0); }
12+
unsafe { copy_nonoverlapping(std::ptr::null(), ptr, 0); } //~ ERROR: invalid use of NULL pointer
1413
}

tests/compile-fail/copy_overflow.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// error-pattern: overflow computing total size of `copy`
2+
use std::mem;
3+
4+
fn main() {
5+
let x = 0;
6+
let mut y = 0;
7+
unsafe {
8+
(&mut y as *mut i32).copy_from(&x, 1usize << (mem::size_of::<usize>() * 8 - 1));
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(intrinsics)]
2+
3+
// Directly call intrinsic to avoid debug assertions in libstd
4+
extern "rust-intrinsic" {
5+
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
6+
}
7+
8+
fn main() {
9+
unsafe { write_bytes::<u8>(std::ptr::null_mut(), 0, 0) }; //~ ERROR invalid use of NULL pointer
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// error-pattern: overflow computing total size of `write_bytes`
2+
use std::mem;
3+
4+
fn main() {
5+
let mut y = 0;
6+
unsafe {
7+
(&mut y as *mut i32).write_bytes(0u8, 1usize << (mem::size_of::<usize>() * 8 - 1));
8+
}
9+
}

0 commit comments

Comments
 (0)