diff options
| author | Ralf Jung <post@ralfj.de> | 2023-09-04 09:25:39 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2023-09-26 15:32:55 +0200 |
| commit | a993a8bf3f9221c84120a6f111fd1b64a5f19ea4 (patch) | |
| tree | ba02e24000154d041cb08cf19d2daacfa3cbd202 /compiler/rustc_const_eval/src | |
| parent | 8bf0dec101dc458a411401a826994006abd2f022 (diff) | |
| download | rust-a993a8bf3f9221c84120a6f111fd1b64a5f19ea4.tar.gz rust-a993a8bf3f9221c84120a6f111fd1b64a5f19ea4.zip | |
const-eval: make misalignment a hard error
Diffstat (limited to 'compiler/rustc_const_eval/src')
5 files changed, 29 insertions, 105 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 3d758cd01d3..4adfbe336af 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,6 +1,3 @@ -use crate::const_eval::CheckAlignment; -use crate::errors::ConstEvalError; - use either::{Left, Right}; use rustc_hir::def::DefKind; @@ -15,7 +12,9 @@ use rustc_span::source_map::Span; use rustc_target::abi::{self, Abi}; use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter}; +use crate::const_eval::CheckAlignment; use crate::errors; +use crate::errors::ConstEvalError; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ intern_const_alloc_recursive, CtfeValidationMode, GlobalId, Immediate, InternKind, InterpCx, @@ -290,14 +289,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( key.param_env, // Statics (and promoteds inside statics) may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. - CompileTimeInterpreter::new( - CanAccessStatics::from(is_static), - if tcx.sess.opts.unstable_opts.extra_const_ub_checks { - CheckAlignment::Error - } else { - CheckAlignment::FutureIncompat - }, - ), + CompileTimeInterpreter::new(CanAccessStatics::from(is_static), CheckAlignment::Error), ); let res = ecx.load_mir(cid.instance.def, cid.promoted); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 14b9894aad5..623b682535e 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -1,10 +1,9 @@ use rustc_hir::def::DefKind; -use rustc_hir::{LangItem, CRATE_HIR_ID}; +use rustc_hir::LangItem; use rustc_middle::mir; use rustc_middle::mir::interpret::PointerArithmetic; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::lint::builtin::INVALID_ALIGNMENT; use std::borrow::Borrow; use std::hash::Hash; use std::ops::ControlFlow; @@ -21,11 +20,11 @@ use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi as CallAbi; use crate::errors::{LongRunning, LongRunningWarn}; +use crate::fluent_generated as fluent; use crate::interpret::{ self, compile_time_machine, AllocId, ConstAllocation, FnArg, FnVal, Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, Scalar, }; -use crate::{errors, fluent_generated as fluent}; use super::error::*; @@ -65,22 +64,11 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { #[derive(Copy, Clone)] pub enum CheckAlignment { - /// Ignore alignment when following relocations. + /// Ignore all alignment requirements. /// This is mainly used in interning. No, /// Hard error when dereferencing a misaligned pointer. Error, - /// Emit a future incompat lint when dereferencing a misaligned pointer. - FutureIncompat, -} - -impl CheckAlignment { - pub fn should_check(&self) -> bool { - match self { - CheckAlignment::No => false, - CheckAlignment::Error | CheckAlignment::FutureIncompat => true, - } - } } #[derive(Copy, Clone, PartialEq)] @@ -358,8 +346,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error #[inline(always)] - fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment { - ecx.machine.check_alignment + fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { + matches!(ecx.machine.check_alignment, CheckAlignment::Error) } #[inline(always)] @@ -367,39 +355,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks || layout.abi.is_uninhabited() } - fn alignment_check_failed( - ecx: &InterpCx<'mir, 'tcx, Self>, - has: Align, - required: Align, - check: CheckAlignment, - ) -> InterpResult<'tcx, ()> { - let err = err_ub!(AlignmentCheckFailed { has, required }).into(); - match check { - CheckAlignment::Error => Err(err), - CheckAlignment::No => span_bug!( - ecx.cur_span(), - "`alignment_check_failed` called when no alignment check requested" - ), - CheckAlignment::FutureIncompat => { - let (_, backtrace) = err.into_parts(); - backtrace.print_backtrace(); - let (span, frames) = super::get_span_and_frames(&ecx); - - ecx.tcx.emit_spanned_lint( - INVALID_ALIGNMENT, - ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID), - span, - errors::AlignmentCheckFailed { - has: has.bytes(), - required: required.bytes(), - frames, - }, - ); - Ok(()) - } - } - } - fn load_mir( ecx: &InterpCx<'mir, 'tcx, Self>, instance: ty::InstanceDef<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index aaa674a598f..73b2251c41e 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -11,11 +11,9 @@ use rustc_middle::mir; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; -use rustc_target::abi::{Align, Size}; +use rustc_target::abi::Size; use rustc_target::spec::abi::Abi as CallAbi; -use crate::const_eval::CheckAlignment; - use super::{ AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, PlaceTy, Pointer, Provenance, @@ -134,7 +132,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { const POST_MONO_CHECKS: bool = true; /// Whether memory accesses should be alignment-checked. - fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment; + fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether, when checking alignment, we should look at the actual address and thus support /// custom alignment logic based on whatever the integer address happens to be. @@ -142,13 +140,6 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// If this returns true, Provenance::OFFSET_IS_ADDR must be true. fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; - fn alignment_check_failed( - ecx: &InterpCx<'mir, 'tcx, Self>, - has: Align, - required: Align, - check: CheckAlignment, - ) -> InterpResult<'tcx, ()>; - /// Whether to enforce the validity invariant for a specific layout. fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 436c4d521a5..13b042cb86a 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -18,7 +18,6 @@ use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; -use crate::const_eval::CheckAlignment; use crate::fluent_generated as fluent; use super::{ @@ -373,8 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.check_and_deref_ptr( ptr, size, - align, - M::enforce_alignment(self), + M::enforce_alignment(self).then_some(align), CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, prov| { let (size, align) = self @@ -395,17 +393,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { align: Align, msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { - self.check_and_deref_ptr( - ptr, - size, - align, - CheckAlignment::Error, - msg, - |alloc_id, _, _| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; - Ok((size, align, ())) - }, - )?; + self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| { + let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; + Ok((size, align, ())) + })?; Ok(()) } @@ -419,8 +410,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, ptr: Pointer<Option<M::Provenance>>, size: Size, - align: Align, - check: CheckAlignment, + align: Option<Align>, msg: CheckInAllocMsg, alloc_size: impl FnOnce( AllocId, @@ -436,8 +426,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub!(DanglingIntPointer(addr, msg)); } // Must be aligned. - if check.should_check() { - self.check_offset_align(addr, align, check)?; + if let Some(align) = align { + self.check_offset_align(addr, align)?; } None } @@ -460,16 +450,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. - if check.should_check() { + if let Some(align) = align { if M::use_addr_for_alignment_check(self) { // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. - self.check_offset_align(ptr.addr().bytes(), align, check)?; + self.check_offset_align(ptr.addr().bytes(), align)?; } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { - M::alignment_check_failed(self, alloc_align, align, check)?; + throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align }); } - self.check_offset_align(offset.bytes(), align, check)?; + self.check_offset_align(offset.bytes(), align)?; } } @@ -480,18 +470,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } - fn check_offset_align( - &self, - offset: u64, - align: Align, - check: CheckAlignment, - ) -> InterpResult<'tcx> { + fn check_offset_align(&self, offset: u64, align: Align) -> InterpResult<'tcx> { if offset % align.bytes() == 0 { Ok(()) } else { // The biggest power of two through which `offset` is divisible. let offset_pow2 = 1 << offset.trailing_zeros(); - M::alignment_check_failed(self, Align::from_bytes(offset_pow2).unwrap(), align, check) + throw_ub!(AlignmentCheckFailed { + has: Align::from_bytes(offset_pow2).unwrap(), + required: align + }); } } } @@ -609,8 +597,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr_and_alloc = self.check_and_deref_ptr( ptr, size, - align, - M::enforce_alignment(self), + M::enforce_alignment(self).then_some(align), CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, prov| { let alloc = self.get_alloc_raw(alloc_id)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 503004cbbe1..4617e1f0143 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -500,8 +500,7 @@ where .size_and_align_of_mplace(&mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); // Due to packed places, only `mplace.align` matters. - let align = - if M::enforce_alignment(self).should_check() { mplace.align } else { Align::ONE }; + let align = if M::enforce_alignment(self) { mplace.align } else { Align::ONE }; self.check_ptr_access_align(mplace.ptr(), size, align, CheckInAllocMsg::DerefTest)?; Ok(()) } |
