Merge pull request #691 from RalfJung/pragmatic-ptr-eq
be pragmatic about ptr-int comparisons, for now
This commit is contained in:
commit
f6fef3b08b
@ -152,8 +152,9 @@ fn ptr_eq(
|
|||||||
// This accepts one-past-the end. Thus, there is still technically
|
// This accepts one-past-the end. Thus, there is still technically
|
||||||
// some non-determinism that we do not fully rule out when two
|
// some non-determinism that we do not fully rule out when two
|
||||||
// allocations sit right next to each other. The C/C++ standards are
|
// allocations sit right next to each other. The C/C++ standards are
|
||||||
// somewhat fuzzy about this case, so I think for now this check is
|
// somewhat fuzzy about this case, so pragmatically speaking I think
|
||||||
// "good enough".
|
// for now this check is "good enough".
|
||||||
|
// FIXME: Once we support intptrcast, we could try to fix these holes.
|
||||||
// Dead allocations in miri cannot overlap with live allocations, but
|
// Dead allocations in miri cannot overlap with live allocations, but
|
||||||
// on read hardware this can easily happen. Thus for comparisons we require
|
// on read hardware this can easily happen. Thus for comparisons we require
|
||||||
// both pointers to be live.
|
// both pointers to be live.
|
||||||
@ -169,8 +170,17 @@ fn ptr_eq(
|
|||||||
assert_eq!(size as u64, self.pointer_size().bytes());
|
assert_eq!(size as u64, self.pointer_size().bytes());
|
||||||
let bits = bits as u64;
|
let bits = bits as u64;
|
||||||
|
|
||||||
// Case I: Comparing with NULL.
|
// Case I: Comparing real pointers with "small" integers.
|
||||||
if bits == 0 {
|
// Really we should only do this for NULL, but pragmatically speaking on non-bare-metal systems,
|
||||||
|
// an allocation will never be at the very bottom of the address space.
|
||||||
|
// Such comparisons can arise when comparing empty slices, which sometimes are "fake"
|
||||||
|
// integer pointers (okay because the slice is empty) and sometimes point into a
|
||||||
|
// real allocation.
|
||||||
|
// The most common source of such integer pointers is `NonNull::dangling()`, which
|
||||||
|
// equals the type's alignment. i128 might have an alignment of 16 bytes, but few types have
|
||||||
|
// alignment 32 or higher, hence the limit of 32.
|
||||||
|
// FIXME: Once we support intptrcast, we could try to fix these holes.
|
||||||
|
if bits < 32 {
|
||||||
// Test if the ptr is in-bounds. Then it cannot be NULL.
|
// Test if the ptr is in-bounds. Then it cannot be NULL.
|
||||||
// Even dangling pointers cannot be NULL.
|
// Even dangling pointers cannot be NULL.
|
||||||
if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() {
|
if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use std::mem;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let b = Box::new(0);
|
let b = Box::new(0);
|
||||||
let x = &*b as *const i32;
|
let x = &*b as *const i32;
|
||||||
// We cannot compare this with a non-NULL integer. After all, these *could* be equal (with the right base address).
|
// We cannot compare this with a non-NULL integer. After all, these *could* be equal (with the right base address).
|
||||||
assert!(x != mem::align_of::<i32>() as *const i32); //~ ERROR invalid arithmetic on pointers
|
assert!(x != 64 as *const i32); //~ ERROR invalid arithmetic on pointers
|
||||||
}
|
}
|
||||||
|
@ -85,4 +85,8 @@ fn main() {
|
|||||||
assert_eq!(make_vec_macro(), [1, 2]);
|
assert_eq!(make_vec_macro(), [1, 2]);
|
||||||
assert_eq!(make_vec_macro_repeat(), [42; 5]);
|
assert_eq!(make_vec_macro_repeat(), [42; 5]);
|
||||||
assert_eq!(make_vec_macro_repeat_zeroed(), [0; 7]);
|
assert_eq!(make_vec_macro_repeat_zeroed(), [0; 7]);
|
||||||
|
|
||||||
|
// Test interesting empty slice comparison
|
||||||
|
// (one is a real pointer, one an integer pointer).
|
||||||
|
assert_eq!((200..-5).step_by(1).collect::<Vec<isize>>(), []);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user