From 850a0d725fe4593645642b142e79037420030c4a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 20 Jun 2019 15:35:06 +0200 Subject: [PATCH 1/2] bump Rust, no changes needed --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index 9d2a8772234..1999b58c89c 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -374c63e0fc356eb61b1966cb6026a2a49fe9226d +4fb77a0398d0339f35f1b18595b375428babd431 From 04fa38dd1bd52c098a731893bbf5b274a4911d0c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 20 Jun 2019 16:38:55 +0200 Subject: [PATCH 2/2] allow some inequality comparisons between pointers and integers --- src/operator.rs | 21 +++++++++++++++++++++ tests/compile-fail/ptr_ge_integer.rs | 7 +++++++ tests/run-pass/pointers.rs | 7 +++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/compile-fail/ptr_ge_integer.rs diff --git a/src/operator.rs b/src/operator.rs index 336f945c784..b05d435ef64 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -109,6 +109,27 @@ fn ptr_op( err!(InvalidPointerMath) } } + Gt | Ge if left.is_ptr() && right.is_bits() => { + // "ptr >[=] integer" can be tested if the integer is small enough. + let left = left.to_ptr().expect("we checked is_ptr"); + let right = right.to_bits(self.memory().pointer_size()).expect("we checked is_bits"); + let (_alloc_size, alloc_align) = self.memory() + .get_size_and_align(left.alloc_id, InboundsCheck::MaybeDead) + .expect("determining size+align of dead ptr cannot fail"); + let min_ptr_val = u128::from(alloc_align.bytes()) + u128::from(left.offset.bytes()); + let result = match bin_op { + Gt => min_ptr_val > right, + Ge => min_ptr_val >= right, + _ => bug!(), + }; + if result { + // Definitely true! + Ok((Scalar::from_bool(true), false)) + } else { + // Sorry, can't tell. + err!(InvalidPointerMath) + } + } // These work if the left operand is a pointer, and the right an integer Add | BitAnd | Sub | Rem if left.is_ptr() && right.is_bits() => { // Cast to i128 is fine as we checked the kind to be ptr-sized diff --git a/tests/compile-fail/ptr_ge_integer.rs b/tests/compile-fail/ptr_ge_integer.rs new file mode 100644 index 00000000000..43160249c36 --- /dev/null +++ b/tests/compile-fail/ptr_ge_integer.rs @@ -0,0 +1,7 @@ +fn main() { + let b = Box::new(0); + let x = &*b as *const i32; + // We cannot test if this is >= 64. After all, depending on the base address, that + // might or might not be the case. + assert!(x >= 64 as *const i32); //~ ERROR invalid arithmetic on pointers +} diff --git a/tests/run-pass/pointers.rs b/tests/run-pass/pointers.rs index 2b26791328d..e0847de97ba 100644 --- a/tests/run-pass/pointers.rs +++ b/tests/run-pass/pointers.rs @@ -83,4 +83,11 @@ fn main() { assert!(dangling != 5usize); assert!(dangling != 6usize); assert!(dangling != 7usize); + + // Using inequality to do the comparison. + assert!(dangling > 0); + assert!(dangling > 1); + assert!(dangling > 2); + assert!(dangling > 3); + assert!(dangling >= 4); }