From 378d9d41720fe2a8a2aec1b39551d11fac6d8ec6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 16 Apr 2019 17:47:37 +0200 Subject: [PATCH] be pragmatic about ptr-int comparisons, for now --- src/operator.rs | 18 ++++++++++++++---- tests/run-pass/vecs.rs | 4 ++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/operator.rs b/src/operator.rs index a30b11aeb27..45c0e63542d 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -152,8 +152,9 @@ fn ptr_eq( // This accepts one-past-the end. Thus, there is still technically // some non-determinism that we do not fully rule out when two // 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 - // "good enough". + // somewhat fuzzy about this case, so pragmatically speaking I think + // 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 // on read hardware this can easily happen. Thus for comparisons we require // both pointers to be live. @@ -169,8 +170,17 @@ fn ptr_eq( assert_eq!(size as u64, self.pointer_size().bytes()); let bits = bits as u64; - // Case I: Comparing with NULL. - if bits == 0 { + // Case I: Comparing real pointers with "small" integers. + // 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. // Even dangling pointers cannot be NULL. if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() { diff --git a/tests/run-pass/vecs.rs b/tests/run-pass/vecs.rs index bb9e5068f91..739def80497 100644 --- a/tests/run-pass/vecs.rs +++ b/tests/run-pass/vecs.rs @@ -85,4 +85,8 @@ fn main() { assert_eq!(make_vec_macro(), [1, 2]); assert_eq!(make_vec_macro_repeat(), [42; 5]); 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::>(), []); } -- 2.44.0