Auto merge of #66083 - RalfJung:miri-offset-from, r=oli-obk

fix Miri offset_from

This is needed to make https://github.com/rust-lang/miri/pull/1032 pass.
This commit is contained in:
bors 2019-11-05 12:46:29 +00:00
commit 3a1b3b30c6
4 changed files with 85 additions and 11 deletions

View file

@ -251,8 +251,28 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
"ptr_offset_from" => {
let a = self.read_immediate(args[0])?.to_scalar()?.to_ptr()?;
let b = self.read_immediate(args[1])?.to_scalar()?.to_ptr()?;
let isize_layout = self.layout_of(self.tcx.types.isize)?;
let a = self.read_immediate(args[0])?.to_scalar()?;
let b = self.read_immediate(args[1])?.to_scalar()?;
// Special case: if both scalars are *equal integers*
// and not NULL, we pretend there is an allocation of size 0 right there,
// and their offset is 0. (There's never a valid object at NULL, making it an
// exception from the exception.)
// This is the dual to the special exception for offset-by-0
// in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
if a.is_bits() && b.is_bits() {
let a = a.to_usize(self)?;
let b = b.to_usize(self)?;
if a == b && a != 0 {
self.write_scalar(Scalar::from_int(0, isize_layout.size), dest)?;
return Ok(true);
}
}
// General case: we need two pointers.
let a = self.force_ptr(a)?;
let b = self.force_ptr(b)?;
if a.alloc_id != b.alloc_id {
throw_ub_format!(
"ptr_offset_from cannot compute offset of pointers into different \
@ -266,7 +286,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
BinOp::Sub, a_offset, b_offset,
)?;
let pointee_layout = self.layout_of(substs.type_at(0))?;
let isize_layout = self.layout_of(self.tcx.types.isize)?;
let val = ImmTy::from_scalar(val, isize_layout);
let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
self.exact_div(val, size, dest)?;

View file

@ -40,8 +40,14 @@ pub const OVERFLOW: isize = {
unsafe { (base_ptr as *const u8).offset_from(field_ptr) }
};
pub const OFFSET_EQUAL_INTS: isize = {
let ptr = 1 as *const u8;
unsafe { ptr.offset_from(ptr) }
};
fn main() {
assert_eq!(OFFSET, 0);
assert_eq!(OFFSET_2, 1);
assert_eq!(OVERFLOW, -1);
assert_eq!(OFFSET_EQUAL_INTS, 0);
}

View file

@ -25,13 +25,25 @@ pub const NOT_PTR: usize = {
unsafe { (42 as *const u8).offset_from(&5u8) as usize }
};
pub const NOT_MULTIPLE_OF_SIZE: usize = {
pub const NOT_MULTIPLE_OF_SIZE: isize = {
//~^ NOTE
let data = [5u8, 6, 7];
let base_ptr = data.as_ptr();
let field_ptr = &data[1] as *const u8 as *const u16;
let offset = unsafe { field_ptr.offset_from(base_ptr as *const u16) };
offset as usize
unsafe { field_ptr.offset_from(base_ptr as *const u16) }
};
pub const OFFSET_FROM_NULL: isize = {
//~^ NOTE
let ptr = 0 as *const u8;
unsafe { ptr.offset_from(ptr) }
};
pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
//~^ NOTE
let ptr1 = 8 as *const u8;
let ptr2 = 16 as *const u8;
unsafe { ptr2.offset_from(ptr1) }
};
fn main() {}

View file

@ -44,18 +44,55 @@ LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| exact_div: 1 cannot be divided by 2 without remainder
| inside call to `std::ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:27
| inside call to `std::ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:33:14
|
::: $DIR/offset_from_ub.rs:28:1
|
LL | / pub const NOT_MULTIPLE_OF_SIZE: usize = {
LL | / pub const NOT_MULTIPLE_OF_SIZE: isize = {
LL | |
LL | | let data = [5u8, 6, 7];
LL | | let base_ptr = data.as_ptr();
... |
LL | | offset as usize
LL | | let field_ptr = &data[1] as *const u8 as *const u16;
LL | | unsafe { field_ptr.offset_from(base_ptr as *const u16) }
LL | | };
| |__-
error: aborting due to 3 previous errors
error: any use of this value will cause an error
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
|
LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| invalid use of NULL pointer
| inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:39:14
|
::: $DIR/offset_from_ub.rs:36:1
|
LL | / pub const OFFSET_FROM_NULL: isize = {
LL | |
LL | | let ptr = 0 as *const u8;
LL | | unsafe { ptr.offset_from(ptr) }
LL | | };
| |__-
error: any use of this value will cause an error
--> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
|
LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| a memory access tried to interpret some bytes as a pointer
| inside call to `std::ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:46:14
|
::: $DIR/offset_from_ub.rs:42:1
|
LL | / pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
LL | |
LL | | let ptr1 = 8 as *const u8;
LL | | let ptr2 = 16 as *const u8;
LL | | unsafe { ptr2.offset_from(ptr1) }
LL | | };
| |__-
error: aborting due to 5 previous errors