Skip to content

Commit a886938

Browse files
committed
Auto merge of #128504 - matthiaskrgr:rollup-pawylnk, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #127490 (Add target page for riscv64gc-unknown-linux-gnu) - #128433 (fix(hermit): `deny(unsafe_op_in_unsafe_fn)`) - #128482 (interpret: on a signed deref check, mention the right pointer in the error) - #128496 (Fix removed `box_syntax` diagnostic if source isn't available) - #128497 (fix dropck documentation for `[T;0]` special-case) - #128499 (chore: refactor backtrace formatting) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e60ebb2 + e6b6d04 commit a886938

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+500
-417
lines changed

compiler/rustc_abi/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ impl Size {
516516
/// Truncates `value` to `self` bits and then sign-extends it to 128 bits
517517
/// (i.e., if it is negative, fill with 1's on the left).
518518
#[inline]
519-
pub fn sign_extend(self, value: u128) -> u128 {
519+
pub fn sign_extend(self, value: u128) -> i128 {
520520
let size = self.bits();
521521
if size == 0 {
522522
// Truncated until nothing is left.
@@ -526,7 +526,7 @@ impl Size {
526526
let shift = 128 - size;
527527
// Shift the unsigned value to the left, then shift back to the right as signed
528528
// (essentially fills with sign bit on the left).
529-
(((value << shift) as i128) >> shift) as u128
529+
((value << shift) as i128) >> shift
530530
}
531531

532532
/// Truncates `value` to `self` bits.
@@ -544,7 +544,7 @@ impl Size {
544544

545545
#[inline]
546546
pub fn signed_int_min(&self) -> i128 {
547-
self.sign_extend(1_u128 << (self.bits() - 1)) as i128
547+
self.sign_extend(1_u128 << (self.bits() - 1))
548548
}
549549

550550
#[inline]

compiler/rustc_const_eval/messages.ftl

+26-11
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,18 @@ const_eval_exact_div_has_remainder =
8888
exact_div: {$a} cannot be divided by {$b} without remainder
8989
9090
const_eval_expected_inbounds_pointer =
91-
expected {$inbounds_size ->
92-
[0] a pointer to some allocation
93-
[1] a pointer to 1 byte of memory
94-
*[x] a pointer to {$inbounds_size} bytes of memory
91+
expected a pointer to {$inbounds_size_abs ->
92+
[0] some allocation
93+
*[x] {$inbounds_size_is_neg ->
94+
[false] {$inbounds_size_abs ->
95+
[1] 1 byte of memory
96+
*[x] {$inbounds_size_abs} bytes of memory
97+
}
98+
*[true] the end of {$inbounds_size_abs ->
99+
[1] 1 byte of memory
100+
*[x] {$inbounds_size_abs} bytes of memory
101+
}
102+
}
95103
}
96104
97105
const_eval_extern_static =
@@ -243,7 +251,7 @@ const_eval_offset_from_different_allocations =
243251
const_eval_offset_from_overflow =
244252
`{$name}` called when first pointer is too far ahead of second
245253
const_eval_offset_from_test =
246-
out-of-bounds `offset_from`
254+
out-of-bounds `offset_from` origin
247255
const_eval_offset_from_underflow =
248256
`{$name}` called when first pointer is too far before second
249257
const_eval_offset_from_unsigned_overflow =
@@ -269,17 +277,24 @@ const_eval_partial_pointer_copy =
269277
const_eval_partial_pointer_overwrite =
270278
unable to overwrite parts of a pointer in memory at {$ptr}
271279
const_eval_pointer_arithmetic_overflow =
272-
overflowing in-bounds pointer arithmetic
280+
overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
273281
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
274282
const_eval_pointer_out_of_bounds =
275283
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
276284
[true] which points to before the beginning of the allocation
277-
*[false] {$alloc_size_minus_ptr_offset ->
278-
[0] which is at or beyond the end of the allocation of size {$alloc_size ->
279-
[1] 1 byte
280-
*[x] {$alloc_size} bytes
285+
*[false] {$inbounds_size_is_neg ->
286+
[true] {$ptr_offset_abs ->
287+
[0] which is at the beginning of the allocation
288+
*[other] which does not have enough space to the beginning of the allocation
289+
}
290+
*[false] {$alloc_size_minus_ptr_offset ->
291+
[0] which is at or beyond the end of the allocation of size {$alloc_size ->
292+
[1] 1 byte
293+
*[x] {$alloc_size} bytes
294+
}
295+
[1] which is only 1 byte from the end of the allocation
296+
*[x] which is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
281297
}
282-
*[x] and there are only {$alloc_size_minus_ptr_offset} bytes starting at that pointer
283298
}
284299
}
285300
const_eval_pointer_use_after_free =

compiler/rustc_const_eval/src/const_eval/machine.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
295295
);
296296
}
297297

298-
match self.ptr_try_get_alloc_id(ptr) {
298+
match self.ptr_try_get_alloc_id(ptr, 0) {
299299
Ok((alloc_id, offset, _extra)) => {
300300
let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id);
301301

@@ -510,7 +510,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
510510

511511
// If an allocation is created in an another const,
512512
// we don't deallocate it.
513-
let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr)?;
513+
let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr, 0)?;
514514
let is_allocated_in_another_const = matches!(
515515
ecx.tcx.try_get_global_alloc(alloc_id),
516516
Some(interpret::GlobalAlloc::Memory(_))

compiler/rustc_const_eval/src/errors.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::borrow::Cow;
2+
use std::fmt::Write;
23

34
use either::Either;
45
use rustc_errors::codes::*;
@@ -15,7 +16,7 @@ use rustc_middle::mir::interpret::{
1516
use rustc_middle::ty::{self, Mutability, Ty};
1617
use rustc_span::Span;
1718
use rustc_target::abi::call::AdjustForForeignAbiError;
18-
use rustc_target::abi::{Size, WrappingRange};
19+
use rustc_target::abi::WrappingRange;
1920

2021
use crate::interpret::InternKind;
2122

@@ -575,18 +576,21 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
575576
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
576577
}
577578
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
578-
diag.arg("alloc_size", alloc_size.bytes())
579-
.arg("inbounds_size", inbounds_size.bytes())
580-
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
581-
diag.arg(
582-
"pointer",
583-
Pointer::new(
584-
Some(CtfeProvenance::from(alloc_id)),
585-
Size::from_bytes(ptr_offset as u64),
586-
)
587-
.to_string(),
588-
);
579+
diag.arg("alloc_size", alloc_size.bytes());
580+
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
581+
diag.arg("pointer", {
582+
let mut out = format!("{:?}", alloc_id);
583+
if ptr_offset > 0 {
584+
write!(out, "+{:#x}", ptr_offset).unwrap();
585+
} else if ptr_offset < 0 {
586+
write!(out, "-{:#x}", ptr_offset.unsigned_abs()).unwrap();
587+
}
588+
out
589+
});
590+
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
591+
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
589592
diag.arg("ptr_offset_is_neg", ptr_offset < 0);
593+
diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs());
590594
diag.arg(
591595
"alloc_size_minus_ptr_offset",
592596
alloc_size.bytes().saturating_sub(ptr_offset as u64),
@@ -600,7 +604,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
600604
);
601605
}
602606

603-
diag.arg("inbounds_size", inbounds_size.bytes());
607+
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
608+
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
604609
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
605610
}
606611
AlignmentCheckFailed(Misalignment { required, has }, msg) => {

compiler/rustc_const_eval/src/interpret/eval_context.rs

-11
Original file line numberDiff line numberDiff line change
@@ -560,17 +560,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
560560
self.frame().body
561561
}
562562

563-
#[inline(always)]
564-
pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
565-
assert!(ty.abi.is_signed());
566-
ty.size.sign_extend(value)
567-
}
568-
569-
#[inline(always)]
570-
pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
571-
ty.size.truncate(value)
572-
}
573-
574563
#[inline]
575564
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
576565
ty.is_freeze(*self.tcx, self.param_env)

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
206206
} else {
207207
(val_bits >> shift_bits) | (val_bits << inv_shift_bits)
208208
};
209-
let truncated_bits = self.truncate(result_bits, layout_val);
209+
let truncated_bits = layout_val.size.truncate(result_bits);
210210
let result = Scalar::from_uint(truncated_bits, layout_val.size);
211211
self.write_scalar(result, dest)?;
212212
}
@@ -243,7 +243,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
243243
let (a_offset, b_offset, is_addr) = if M::Provenance::OFFSET_IS_ADDR {
244244
(a.addr().bytes(), b.addr().bytes(), /*is_addr*/ true)
245245
} else {
246-
match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
246+
match (self.ptr_try_get_alloc_id(a, 0), self.ptr_try_get_alloc_id(b, 0)) {
247247
(Err(a), Err(b)) => {
248248
// Neither pointer points to an allocation, so they are both absolute.
249249
(a, b, /*is_addr*/ true)
@@ -312,7 +312,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
312312
};
313313

314314
// Check that the memory between them is dereferenceable at all, starting from the
315-
// base pointer: `dist` is `a - b`, so it is based on `b`.
315+
// origin pointer: `dist` is `a - b`, so it is based on `b`.
316316
self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)?;
317317
// Then check that this is also dereferenceable from `a`. This ensures that they are
318318
// derived from the same allocation.
@@ -580,13 +580,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
580580
ptr: Pointer<Option<M::Provenance>>,
581581
offset_bytes: i64,
582582
) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
583-
// We first compute the pointer with overflow checks, to get a specific error for when it
584-
// overflows (though technically this is redundant with the following inbounds check).
585-
let result = ptr.signed_offset(offset_bytes, self)?;
586583
// The offset must be in bounds starting from `ptr`.
587584
self.check_ptr_access_signed(ptr, offset_bytes, CheckInAllocMsg::PointerArithmeticTest)?;
588-
// Done.
589-
Ok(result)
585+
// This also implies that there is no overflow, so we are done.
586+
Ok(ptr.wrapping_signed_offset(offset_bytes, self))
590587
}
591588

592589
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.

compiler/rustc_const_eval/src/interpret/machine.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -321,15 +321,21 @@ pub trait Machine<'tcx>: Sized {
321321
ptr: Pointer<Self::Provenance>,
322322
) -> InterpResult<'tcx>;
323323

324-
/// Convert a pointer with provenance into an allocation-offset pair
325-
/// and extra provenance info.
324+
/// Convert a pointer with provenance into an allocation-offset pair and extra provenance info.
325+
/// `size` says how many bytes of memory are expected at that pointer. The *sign* of `size` can
326+
/// be used to disambiguate situations where a wildcard pointer sits right in between two
327+
/// allocations.
326328
///
327-
/// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`.
329+
/// If `ptr.provenance.get_alloc_id()` is `Some(p)`, the returned `AllocId` must be `p`.
330+
/// The resulting `AllocId` will just be used for that one step and the forgotten again
331+
/// (i.e., we'll never turn the data returned here back into a `Pointer` that might be
332+
/// stored in machine state).
328333
///
329334
/// When this fails, that means the pointer does not point to a live allocation.
330335
fn ptr_get_alloc(
331336
ecx: &InterpCx<'tcx, Self>,
332337
ptr: Pointer<Self::Provenance>,
338+
size: i64,
333339
) -> Option<(AllocId, Size, Self::ProvenanceExtra)>;
334340

335341
/// Called to adjust global allocations to the Provenance and AllocExtra of this machine.
@@ -658,6 +664,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
658664
fn ptr_get_alloc(
659665
_ecx: &InterpCx<$tcx, Self>,
660666
ptr: Pointer<CtfeProvenance>,
667+
_size: i64,
661668
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
662669
// We know `offset` is relative to the allocation, so we can use `into_parts`.
663670
let (prov, offset) = ptr.into_parts();

0 commit comments

Comments
 (0)