Auto merge of #1248 - RalfJung:overflow, r=RalfJung

detect UB: overflow in copy/write_bytes

Fixes https://github.com/rust-lang/miri/issues/1234
This commit is contained in:
bors 2020-03-21 17:09:57 +00:00
commit 7f476266fd
6 changed files with 42 additions and 6 deletions

7
miri
View File

@ -11,6 +11,9 @@ working directory.
./miri build <flags>:
Just build miri. <flags> are passed to `cargo build`.
./miri check <flags>:
Just check miri. <flags> are passed to `cargo check`.
./miri test <flags>:
Build miri, set up a sysroot and then run the test suite. <flags> are passed
to the final `cargo test` invocation.
@ -99,6 +102,10 @@ install|install-debug)
# "--offline" to avoid querying the registry (for yanked packages).
exec cargo install $CARGO_INSTALL_FLAGS --path "$(dirname "$0")" --force --locked --offline "$@"
;;
check|check-debug)
# Check, and let caller control flags.
exec cargo check $CARGO_BUILD_FLAGS "$@"
;;
build|build-debug)
# Build, and let caller control flags.
exec cargo build $CARGO_BUILD_FLAGS "$@"

View File

@ -4,7 +4,7 @@ use std::convert::TryFrom;
use rustc::mir;
use rustc::mir::interpret::{InterpResult, PointerArithmetic};
use rustc::ty;
use rustc::ty::layout::{Align, LayoutOf, Size};
use rustc::ty::layout::{Align, LayoutOf};
use rustc_apfloat::Float;
use rustc_span::source_map::Span;
@ -226,11 +226,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
=> {
let elem_ty = substs.type_at(0);
let elem_layout = this.layout_of(elem_ty)?;
let elem_size = elem_layout.size.bytes();
let count = this.read_scalar(args[2])?.to_machine_usize(this)?;
let elem_align = elem_layout.align.abi;
let size = Size::from_bytes(count) * elem_size;
let size = elem_layout.size.checked_mul(count, this)
.ok_or_else(|| err_ub_format!("overflow computing total size of `{}`", intrinsic_name))?;
let src = this.read_scalar(args[0])?.not_undef()?;
let src = this.memory.check_ptr_access(src, size, elem_align)?;
let dest = this.read_scalar(args[1])?.not_undef()?;
@ -493,7 +493,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let val_byte = this.read_scalar(args[1])?.to_u8()?;
let ptr = this.read_scalar(args[0])?.not_undef()?;
let count = this.read_scalar(args[2])?.to_machine_usize(this)?;
let byte_count = ty_layout.size * count;
let byte_count = ty_layout.size.checked_mul(count, this)
.ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?;
this.memory
.write_bytes(ptr, iter::repeat(val_byte).take(byte_count.bytes() as usize))?;
}

View File

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

View File

@ -0,0 +1,10 @@
// error-pattern: overflow computing total size of `copy`
use std::mem;
fn main() {
let x = 0;
let mut y = 0;
unsafe {
(&mut y as *mut i32).copy_from(&x, 1usize << (mem::size_of::<usize>() * 8 - 1));
}
}

View File

@ -0,0 +1,10 @@
#![feature(intrinsics)]
// Directly call intrinsic to avoid debug assertions in libstd
extern "rust-intrinsic" {
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
}
fn main() {
unsafe { write_bytes::<u8>(std::ptr::null_mut(), 0, 0) }; //~ ERROR invalid use of NULL pointer
}

View File

@ -0,0 +1,9 @@
// error-pattern: overflow computing total size of `write_bytes`
use std::mem;
fn main() {
let mut y = 0;
unsafe {
(&mut y as *mut i32).write_bytes(0u8, 1usize << (mem::size_of::<usize>() * 8 - 1));
}
}