Skip to content

Commit 2c6a29a

Browse files
committed
Auto merge of rust-lang#94860 - Dylan-DPC:rollup-n06j8h6, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - rust-lang#87618 (Add missing documentation for std::char types) - rust-lang#94769 (Collapse blanket and auto-trait impls by default) - rust-lang#94798 (`parse_tt` refactorings) - rust-lang#94818 (Rename `IntoFuture::Future` to `IntoFuture::IntoFuture`) - rust-lang#94827 (CTFE/Miri: detect out-of-bounds pointers in offset_from) - rust-lang#94838 (Make float parsing docs more comprehensive) - rust-lang#94839 (Suggest using double colon when a struct field type include single colon) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 335ffbf + 298c9a0 commit 2c6a29a

File tree

16 files changed

+334
-183
lines changed

16 files changed

+334
-183
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+42-38
Original file line numberDiff line numberDiff line change
@@ -307,53 +307,57 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
307307
self.write_pointer(offset_ptr, dest)?;
308308
}
309309
sym::ptr_offset_from => {
310-
let a = self.read_immediate(&args[0])?.to_scalar()?;
311-
let b = self.read_immediate(&args[1])?.to_scalar()?;
310+
let a = self.read_pointer(&args[0])?;
311+
let b = self.read_pointer(&args[1])?;
312312

313313
// Special case: if both scalars are *equal integers*
314314
// and not null, we pretend there is an allocation of size 0 right there,
315315
// and their offset is 0. (There's never a valid object at null, making it an
316316
// exception from the exception.)
317317
// This is the dual to the special exception for offset-by-0
318-
// in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
319-
//
320-
// Control flow is weird because we cannot early-return (to reach the
321-
// `go_to_block` at the end).
322-
let done = if let (Ok(a), Ok(b)) = (a.try_to_int(), b.try_to_int()) {
323-
let a = a.try_to_machine_usize(*self.tcx).unwrap();
324-
let b = b.try_to_machine_usize(*self.tcx).unwrap();
325-
if a == b && a != 0 {
318+
// in the inbounds pointer offset operation (see `ptr_offset_inbounds` below).
319+
match (self.memory.ptr_try_get_alloc(a), self.memory.ptr_try_get_alloc(b)) {
320+
(Err(a), Err(b)) if a == b && a != 0 => {
321+
// Both are the same non-null integer.
326322
self.write_scalar(Scalar::from_machine_isize(0, self), dest)?;
327-
true
328-
} else {
329-
false
330323
}
331-
} else {
332-
false
333-
};
334-
335-
if !done {
336-
// General case: we need two pointers.
337-
let a = self.scalar_to_ptr(a);
338-
let b = self.scalar_to_ptr(b);
339-
let (a_alloc_id, a_offset, _) = self.memory.ptr_get_alloc(a)?;
340-
let (b_alloc_id, b_offset, _) = self.memory.ptr_get_alloc(b)?;
341-
if a_alloc_id != b_alloc_id {
342-
throw_ub_format!(
343-
"ptr_offset_from cannot compute offset of pointers into different \
344-
allocations.",
345-
);
324+
(Err(offset), _) | (_, Err(offset)) => {
325+
throw_ub!(DanglingIntPointer(offset, CheckInAllocMsg::OffsetFromTest));
326+
}
327+
(Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
328+
// Both are pointers. They must be into the same allocation.
329+
if a_alloc_id != b_alloc_id {
330+
throw_ub_format!(
331+
"ptr_offset_from cannot compute offset of pointers into different \
332+
allocations.",
333+
);
334+
}
335+
// And they must both be valid for zero-sized accesses ("in-bounds or one past the end").
336+
self.memory.check_ptr_access_align(
337+
a,
338+
Size::ZERO,
339+
Align::ONE,
340+
CheckInAllocMsg::OffsetFromTest,
341+
)?;
342+
self.memory.check_ptr_access_align(
343+
b,
344+
Size::ZERO,
345+
Align::ONE,
346+
CheckInAllocMsg::OffsetFromTest,
347+
)?;
348+
349+
// Compute offset.
350+
let usize_layout = self.layout_of(self.tcx.types.usize)?;
351+
let isize_layout = self.layout_of(self.tcx.types.isize)?;
352+
let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout);
353+
let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout);
354+
let (val, _overflowed, _ty) =
355+
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
356+
let pointee_layout = self.layout_of(substs.type_at(0))?;
357+
let val = ImmTy::from_scalar(val, isize_layout);
358+
let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
359+
self.exact_div(&val, &size, dest)?;
346360
}
347-
let usize_layout = self.layout_of(self.tcx.types.usize)?;
348-
let isize_layout = self.layout_of(self.tcx.types.isize)?;
349-
let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout);
350-
let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout);
351-
let (val, _overflowed, _ty) =
352-
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
353-
let pointee_layout = self.layout_of(substs.type_at(0))?;
354-
let val = ImmTy::from_scalar(val, isize_layout);
355-
let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
356-
self.exact_div(&val, &size, dest)?;
357361
}
358362
}
359363

compiler/rustc_const_eval/src/interpret/memory.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
388388
CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => {
389389
AllocCheck::Dereferenceable
390390
}
391-
CheckInAllocMsg::PointerArithmeticTest | CheckInAllocMsg::InboundsTest => {
392-
AllocCheck::Live
393-
}
391+
CheckInAllocMsg::PointerArithmeticTest
392+
| CheckInAllocMsg::OffsetFromTest
393+
| CheckInAllocMsg::InboundsTest => AllocCheck::Live,
394394
};
395395
let (size, align) = self.get_size_and_align(alloc_id, check)?;
396396
Ok((size, align, ()))

0 commit comments

Comments
 (0)