Skip to content

Commit f1e7572

Browse files
authored
update for rustc Scalar changes, test for pointer wrapping ICE (#744)
update for rustc Scalar changes, test for pointer wrapping ICE
2 parents 3c930e4 + b62ddc2 commit f1e7572

File tree

5 files changed

+29
-20
lines changed

5 files changed

+29
-20
lines changed

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1a56ec4dae92538ab6e0ecf993c61f3b50ed77cf
1+
721268583759224d0f6476e0b8b196cc8afbdea0

src/fn_call.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -607,11 +607,12 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
607607
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
608608
let dtor = match this.read_scalar(args[1])?.not_undef()? {
609609
Scalar::Ptr(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?),
610-
Scalar::Bits { bits: 0, size } => {
610+
Scalar::Raw { data: 0, size } => {
611+
// NULL pointer
611612
assert_eq!(size as u64, this.memory().pointer_size().bytes());
612613
None
613614
},
614-
Scalar::Bits { .. } => return err!(ReadBytesAsPointer),
615+
Scalar::Raw { .. } => return err!(ReadBytesAsPointer),
615616
};
616617

617618
// Figure out how large a pthread TLS key actually is.

src/operator.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
141141
) -> EvalResult<'tcx, bool> {
142142
let size = self.pointer_size();
143143
Ok(match (left, right) {
144-
(Scalar::Bits { .. }, Scalar::Bits { .. }) =>
144+
(Scalar::Raw { .. }, Scalar::Raw { .. }) =>
145145
left.to_bits(size)? == right.to_bits(size)?,
146146
(Scalar::Ptr(left), Scalar::Ptr(right)) => {
147147
// Comparison illegal if one of them is out-of-bounds, *unless* they
@@ -165,10 +165,10 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
165165
}
166166
}
167167
// Comparing ptr and integer.
168-
(Scalar::Ptr(ptr), Scalar::Bits { bits, size }) |
169-
(Scalar::Bits { bits, size }, Scalar::Ptr(ptr)) => {
168+
(Scalar::Ptr(ptr), Scalar::Raw { data, size }) |
169+
(Scalar::Raw { data, size }, Scalar::Ptr(ptr)) => {
170170
assert_eq!(size as u64, self.pointer_size().bytes());
171-
let bits = bits as u64;
171+
let bits = data as u64;
172172

173173
// Case I: Comparing real pointers with "small" integers.
174174
// Really we should only do this for NULL, but pragmatically speaking on non-bare-metal systems,
@@ -262,7 +262,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
262262
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
263263
(value << shift) >> shift
264264
};
265-
let ptr_size = self.memory().pointer_size().bytes() as u8;
265+
let ptr_size = self.memory().pointer_size();
266266
trace!("ptr BitAnd, align {}, operand {:#010x}, base_mask {:#010x}",
267267
ptr_base_align, right, base_mask);
268268
if right & base_mask == base_mask {
@@ -278,7 +278,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
278278
)
279279
} else if right & base_mask == 0 {
280280
// Case 2: the base address bits are all taken away, i.e., right is all-0 there.
281-
(Scalar::Bits { bits: (left.offset.bytes() as u128) & right, size: ptr_size }, false)
281+
let v = Scalar::from_uint((left.offset.bytes() as u128) & right, ptr_size);
282+
(v, false)
282283
} else {
283284
return err!(ReadPointerAsBytes);
284285
}
@@ -289,18 +290,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
289290
// (Intuition: modulo a divisor leaks less information.)
290291
let ptr_base_align = self.memory().get(left.alloc_id)?.align.bytes();
291292
let right = right as u64;
292-
let ptr_size = self.memory().pointer_size().bytes() as u8;
293+
let ptr_size = self.memory().pointer_size();
293294
if right == 1 {
294295
// Modulo 1 is always 0.
295-
(Scalar::Bits { bits: 0, size: ptr_size }, false)
296+
(Scalar::from_uint(0u32, ptr_size), false)
296297
} else if ptr_base_align % right == 0 {
297298
// The base address would be cancelled out by the modulo operation, so we can
298299
// just take the modulo of the offset.
299300
(
300-
Scalar::Bits {
301-
bits: (left.offset.bytes() % right) as u128,
302-
size: ptr_size
303-
},
301+
Scalar::from_uint((left.offset.bytes() % right) as u128, ptr_size),
304302
false,
305303
)
306304
} else {
+8-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
use std::ptr;
2+
13
fn main() {
24
let v = [1i16, 2];
3-
let x = v.as_ptr().wrapping_offset(1); // ptr to the 2nd element
5+
let x = &mut ptr::null(); // going through memory as there are more sanity checks along that path
6+
*x = v.as_ptr().wrapping_offset(1); // ptr to the 2nd element
47
// Adding 2*isize::max and then 1 is like substracting 1
5-
let x = x.wrapping_offset(isize::max_value());
6-
let x = x.wrapping_offset(isize::max_value());
7-
let x = x.wrapping_offset(1);
8-
assert_eq!(unsafe { *x }, 1);
8+
*x = x.wrapping_offset(isize::max_value());
9+
*x = x.wrapping_offset(isize::max_value());
10+
*x = x.wrapping_offset(1);
11+
assert_eq!(unsafe { **x }, 1);
912
}

tests/run-pass/ptr_int_casts.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::mem;
2+
use std::ptr;
23

34
fn eq_ref<T>(x: &T, y: &T) -> bool {
45
x as *const _ == y as *const _
@@ -11,6 +12,12 @@ fn main() {
1112
assert_eq!(1 as *const i32 as usize, 1);
1213
assert_eq!((1 as *const i32).wrapping_offset(4) as usize, 1 + 4*4);
1314

15+
// negative overflowing wrapping_offset (going through memory because
16+
// this used to trigger an ICE on 32bit)
17+
let val = &mut ptr::null();
18+
*val = (1 as *const u8).wrapping_offset(-4);
19+
assert_eq!(*val as usize, usize::max_value() - 2);
20+
1421
{ // ptr-int-ptr
1522
let x = 13;
1623
let mut y = &x as &_ as *const _ as usize;

0 commit comments

Comments
 (0)