Skip to content

Commit 9eb4e00

Browse files
committed
refactor ptr_offset_inbounds: it can be reduced to check_ptr_access, after all!
1 parent c4f1d3f commit 9eb4e00

File tree

1 file changed

+14
-36
lines changed

1 file changed

+14
-36
lines changed

src/operator.rs

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
use std::convert::TryFrom;
22

3-
use rustc::ty::{Ty, layout::LayoutOf};
3+
use rustc::ty::{Ty, layout::{Size, Align, LayoutOf}};
44
use rustc::mir;
55

66
use crate::*;
77

88
pub trait EvalContextExt<'tcx> {
9-
fn pointer_inbounds(
10-
&self,
11-
ptr: Pointer<Tag>
12-
) -> InterpResult<'tcx>;
13-
149
fn binary_ptr_op(
1510
&self,
1611
bin_op: mir::BinOp,
@@ -33,13 +28,6 @@ pub trait EvalContextExt<'tcx> {
3328
}
3429

3530
impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
36-
/// Test if the pointer is in-bounds of a live allocation.
37-
#[inline]
38-
fn pointer_inbounds(&self, ptr: Pointer<Tag>) -> InterpResult<'tcx> {
39-
let (size, _align) = self.memory.get_size_and_align(ptr.alloc_id, AllocCheck::Live)?;
40-
ptr.check_inbounds_alloc(size, CheckInAllocMsg::InboundsTest)
41-
}
42-
4331
fn binary_ptr_op(
4432
&self,
4533
bin_op: mir::BinOp,
@@ -110,9 +98,8 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
11098
}
11199

112100
/// Raises an error if the offset moves the pointer outside of its allocation.
113-
/// We consider ZSTs their own huge allocation that doesn't overlap with anything (and nothing
114-
/// moves in there because the size is 0). We also consider the NULL pointer its own separate
115-
/// allocation, and all the remaining integers pointers their own allocation.
101+
/// For integers, we consider each of them their own tiny allocation of size 0,
102+
/// so offset-by-0 is okay for them -- except for NULL, which we rule out entirely.
116103
fn pointer_offset_inbounds(
117104
&self,
118105
ptr: Scalar<Tag>,
@@ -123,25 +110,16 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
123110
let offset = offset
124111
.checked_mul(pointee_size)
125112
.ok_or_else(|| err_panic!(Overflow(mir::BinOp::Mul)))?;
126-
// Now let's see what kind of pointer this is.
127-
let ptr = if offset == 0 {
128-
match ptr {
129-
Scalar::Ptr(ptr) => ptr,
130-
Scalar::Raw { .. } => {
131-
// Offset 0 on an integer. We accept that, pretending there is
132-
// a little zero-sized allocation here.
133-
return Ok(ptr);
134-
}
135-
}
136-
} else {
137-
// Offset > 0. We *require* a pointer.
138-
self.force_ptr(ptr)?
139-
};
140-
// Both old and new pointer must be in-bounds of a *live* allocation.
141-
// (Of the same allocation, but that part is trivial with our representation.)
142-
self.pointer_inbounds(ptr)?;
143-
let ptr = ptr.signed_offset(offset, self)?;
144-
self.pointer_inbounds(ptr)?;
145-
Ok(Scalar::Ptr(ptr))
113+
// We do this forst, to rule out overflows.
114+
let offset_ptr = ptr.ptr_signed_offset(offset, self)?;
115+
// What we need to check is that starting at `ptr`,
116+
// we could do an access of size `offset`. Alignment does not matter.
117+
self.memory.check_ptr_access(
118+
ptr,
119+
Size::from_bytes(u64::try_from(offset).unwrap()),
120+
Align::from_bytes(1).unwrap(),
121+
)?;
122+
// That's it!
123+
Ok(offset_ptr)
146124
}
147125
}

0 commit comments

Comments
 (0)