detect UB: overflow in copy/write_bytes

This commit is contained in:
Ralf Jung 2020-03-21 17:54:33 +01:00
parent 8acfafe186
commit 238ed49a07
3 changed files with 24 additions and 4 deletions

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

@ -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,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));
}
}