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:
commit
7f476266fd
7
miri
7
miri
@ -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 "$@"
|
||||
|
@ -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))?;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
10
tests/compile-fail/copy_overflow.rs
Normal file
10
tests/compile-fail/copy_overflow.rs
Normal 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));
|
||||
}
|
||||
}
|
10
tests/compile-fail/write_bytes_null.rs
Normal file
10
tests/compile-fail/write_bytes_null.rs
Normal 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
|
||||
}
|
9
tests/compile-fail/write_bytes_overflow.rs
Normal file
9
tests/compile-fail/write_bytes_overflow.rs
Normal 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));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user