check the assumptions made by the unchecked_ and copy_nonoverlapping intrinsics
This commit is contained in:
parent
f118ff43e7
commit
ffd482e2f5
6 changed files with 85 additions and 6 deletions
|
|
@ -1022,7 +1022,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
fn copy(&mut self, src: PrimVal, dest: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx> {
|
||||
let size = self.type_size(ty)?.expect("cannot copy from an unsized type");
|
||||
let align = self.type_align(ty)?;
|
||||
self.memory.copy(src, dest, size, align)?;
|
||||
self.memory.copy(src, dest, size, align, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy(&mut self, src: PrimVal, dest: PrimVal, size: u64, align: u64) -> EvalResult<'tcx> {
|
||||
pub fn copy(&mut self, src: PrimVal, dest: PrimVal, size: u64, align: u64, nonoverlapping: bool) -> EvalResult<'tcx> {
|
||||
if size == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
|
@ -675,6 +675,12 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
|||
unsafe {
|
||||
assert_eq!(size as usize as u64, size);
|
||||
if src.alloc_id == dest.alloc_id {
|
||||
if nonoverlapping {
|
||||
if (src.offset <= dest.offset && src.offset + size > dest.offset) ||
|
||||
(dest.offset <= src.offset && dest.offset + size > src.offset) {
|
||||
return Err(EvalError::Intrinsic(format!("copy_nonoverlapping called on overlapping ranges")));
|
||||
}
|
||||
}
|
||||
ptr::copy(src_bytes, dest_bytes, size as usize);
|
||||
} else {
|
||||
ptr::copy_nonoverlapping(src_bytes, dest_bytes, size as usize);
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
|
||||
"copy" |
|
||||
"copy_nonoverlapping" => {
|
||||
// FIXME: check whether overlapping occurs
|
||||
let elem_ty = substs.type_at(0);
|
||||
let elem_size = self.type_size(elem_ty)?.expect("cannot copy unsized value");
|
||||
if elem_size != 0 {
|
||||
|
|
@ -148,7 +147,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
let src = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let dest = arg_vals[1].read_ptr(&self.memory)?;
|
||||
let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?;
|
||||
self.memory.copy(src, dest, count * elem_size, elem_align)?;
|
||||
self.memory.copy(src, dest, count * elem_size, elem_align, intrinsic_name.ends_with("_nonoverlapping"))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,12 +407,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
"unchecked_shl" => {
|
||||
// FIXME Check for too-wide shifts
|
||||
let bits = self.type_size(dest_ty)?.expect("intrinsic can't be called on unsized type") as u128 * 8;
|
||||
let rhs = self.value_to_primval(arg_vals[1], substs.type_at(0))?.to_bytes()?;
|
||||
if rhs >= bits {
|
||||
return Err(EvalError::Intrinsic(format!("Overflowing shift by {} in unchecked_shl", rhs)));
|
||||
}
|
||||
self.intrinsic_overflowing(mir::BinOp::Shl, &args[0], &args[1], dest, dest_ty)?;
|
||||
}
|
||||
|
||||
"unchecked_shr" => {
|
||||
// FIXME Check for too-wide shifts
|
||||
let bits = self.type_size(dest_ty)?.expect("intrinsic can't be called on unsized type") as u128 * 8;
|
||||
let rhs = self.value_to_primval(arg_vals[1], substs.type_at(0))?.to_bytes()?;
|
||||
if rhs >= bits {
|
||||
return Err(EvalError::Intrinsic(format!("Overflowing shift by {} in unchecked_shr", rhs)));
|
||||
}
|
||||
self.intrinsic_overflowing(mir::BinOp::Shr, &args[0], &args[1], dest, dest_ty)?;
|
||||
}
|
||||
|
||||
|
|
|
|||
24
tests/compile-fail/copy_nonoverlapping.rs
Normal file
24
tests/compile-fail/copy_nonoverlapping.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
use std::intrinsics::*;
|
||||
|
||||
//error-pattern: copy_nonoverlapping called on overlapping ranges
|
||||
|
||||
fn main() {
|
||||
let mut data = [0u8; 16];
|
||||
unsafe {
|
||||
let a = &data[0] as *const _;
|
||||
let b = &mut data[1] as *mut _;
|
||||
std::ptr::copy_nonoverlapping(a, b, 2);
|
||||
}
|
||||
}
|
||||
21
tests/compile-fail/div-by-zero.rs
Normal file
21
tests/compile-fail/div-by-zero.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
use std::intrinsics::*;
|
||||
|
||||
//error-pattern: Division by 0 in unchecked_div
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _n = unchecked_div(1i64, 0);
|
||||
}
|
||||
}
|
||||
21
tests/compile-fail/overflowing-unchecked-rsh.rs
Normal file
21
tests/compile-fail/overflowing-unchecked-rsh.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
use std::intrinsics::*;
|
||||
|
||||
//error-pattern: Overflowing shift by 64 in unchecked_shr
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _n = unchecked_shr(1i64, 64);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue