提交 ffd482e2 编写于 作者: R Ralf Jung

check the assumptions made by the unchecked_ and copy_nonoverlapping intrinsics

上级 f118ff43
......@@ -1022,7 +1022,7 @@ pub(super) fn operand_ty(&self, operand: &mir::Operand<'tcx>) -> Ty<'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 @@ pub fn mark_static_initalized(&mut self, alloc_id: AllocId, mutable: bool) -> Ev
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 @@ pub fn copy(&mut self, src: PrimVal, dest: PrimVal, size: u64, align: u64) -> Ev
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 @@ pub(super) fn call_intrinsic(
"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 @@ pub(super) fn call_intrinsic(
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 @@ pub(super) fn call_intrinsic(
}
"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)?;
}
......
// 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);
}
}
// 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);
}
}
// 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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册