diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2022-05-20 14:03:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-20 14:03:03 +0200 |
| commit | 706aa59efa9d419ada5e54249edd422bd02fe03a (patch) | |
| tree | d54fdc24b369029061b4fdcdd9289701fbaf10f9 /compiler/rustc_const_eval/src/interpret | |
| parent | 62569edcbda509ee243b488b95772730c13dde96 (diff) | |
| parent | 4bb152c4bc5ff5b89e8b3c35908a5ad23e3527fe (diff) | |
| download | rust-706aa59efa9d419ada5e54249edd422bd02fe03a.tar.gz rust-706aa59efa9d419ada5e54249edd422bd02fe03a.zip | |
Rollup merge of #97185 - RalfJung:number-validity, r=oli-obk
interpret/validity: separately control checking numbers for being init and non-ptr This lets Miri control this in a more fine-grained way. r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret')
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/machine.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/memory.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/validity.rs | 24 |
3 files changed, 33 insertions, 15 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index a79751ccb55..1dcd50a5b70 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -133,9 +133,11 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; - /// Whether to enforce validity (e.g., initialization and not having ptr provenance) - /// of integers and floats. - fn enforce_number_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + /// Whether to enforce integers and floats being initialized. + fn enforce_number_init(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + + /// Whether to enforce integers and floats not having provenance. + fn enforce_number_no_provenance(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether function calls should be [ABI](Abi)-checked. fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { @@ -453,7 +455,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn enforce_number_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { + fn enforce_number_init(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { + true + } + + #[inline(always)] + fn enforce_number_no_provenance(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { true } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 33162a01ed2..f5c43b705a8 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -924,10 +924,15 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { self.read_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size)) } - pub fn check_bytes(&self, range: AllocRange, allow_uninit_and_ptr: bool) -> InterpResult<'tcx> { + pub fn check_bytes( + &self, + range: AllocRange, + allow_uninit: bool, + allow_ptr: bool, + ) -> InterpResult<'tcx> { Ok(self .alloc - .check_bytes(&self.tcx, self.range.subrange(range), allow_uninit_and_ptr) + .check_bytes(&self.tcx, self.range.subrange(range), allow_uninit, allow_ptr) .map_err(|e| e.to_interp_error(self.alloc_id))?) } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 8770ed956e6..b39a33aff09 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -536,15 +536,21 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let value = self.read_scalar(value)?; // NOTE: Keep this in sync with the array optimization for int/float // types below! - if M::enforce_number_validity(self.ecx) { - // Integers/floats with number validity: Must be scalar bits, pointers are dangerous. + if M::enforce_number_init(self.ecx) { + try_validation!( + value.check_init(), + self.path, + err_ub!(InvalidUninitBytes(..)) => + { "{:x}", value } expected { "initialized bytes" } + ); + } + if M::enforce_number_no_provenance(self.ecx) { // As a special exception we *do* match on a `Scalar` here, since we truly want // to know its underlying representation (and *not* cast it to an integer). - let is_bits = - value.check_init().map_or(false, |v| matches!(v, Scalar::Int(..))); - if !is_bits { + let is_ptr = value.check_init().map_or(false, |v| matches!(v, Scalar::Ptr(..))); + if is_ptr { throw_validation_failure!(self.path, - { "{:x}", value } expected { "initialized plain (non-pointer) bytes" } + { "{:x}", value } expected { "plain (non-pointer) bytes" } ) } } @@ -651,7 +657,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let size = scalar_layout.size(self.ecx); let is_full_range = match scalar_layout { ScalarAbi::Initialized { .. } => { - if M::enforce_number_validity(self.ecx) { + if M::enforce_number_init(self.ecx) { false // not "full" since uninit is not accepted } else { scalar_layout.is_always_valid(self.ecx) @@ -910,10 +916,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> return Ok(()); }; - let allow_uninit_and_ptr = !M::enforce_number_validity(self.ecx); match alloc.check_bytes( alloc_range(Size::ZERO, size), - allow_uninit_and_ptr, + /*allow_uninit*/ !M::enforce_number_init(self.ecx), + /*allow_ptr*/ !M::enforce_number_no_provenance(self.ecx), ) { // In the happy case, we needn't check anything else. Ok(()) => {} |
