Skip to content

Commit aa5c496

Browse files
committed
Uninit immediates cannot happen in casts or immediate reads
1 parent a2f4fae commit aa5c496

File tree

11 files changed

+33
-42
lines changed

11 files changed

+33
-42
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,6 @@ const_eval_invalid_transmute =
179179
180180
const_eval_invalid_uninit_bytes =
181181
reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory
182-
const_eval_invalid_uninit_bytes_unknown =
183-
using uninitialized data, but this operation requires initialized memory
184182
185183
const_eval_invalid_vtable_pointer =
186184
using {$pointer} as vtable pointer but it does not point to a vtable

compiler/rustc_const_eval/src/const_eval/error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ where
172172
);
173173

174174
if let InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(
175-
Some((alloc_id, _access)),
175+
alloc_id,
176+
_access,
176177
)) = error
177178
{
178179
let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);

compiler/rustc_const_eval/src/errors.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
482482
InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
483483
InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
484484
InvalidStr(_) => const_eval_invalid_str,
485-
InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
486-
InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
485+
InvalidUninitBytes(..) => const_eval_invalid_uninit_bytes,
487486
DeadLocal => const_eval_dead_local,
488487
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
489488
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
@@ -515,7 +514,6 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
515514
| PointerArithOverflow
516515
| InvalidMeta(InvalidMetaKind::SliceTooBig)
517516
| InvalidMeta(InvalidMetaKind::TooBig)
518-
| InvalidUninitBytes(None)
519517
| DeadLocal
520518
| UninhabitedEnumVariantWritten(_)
521519
| UninhabitedEnumVariantRead(_) => {}
@@ -603,7 +601,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
603601
InvalidStr(err) => {
604602
diag.arg("err", format!("{err}"));
605603
}
606-
InvalidUninitBytes(Some((alloc, info))) => {
604+
InvalidUninitBytes(alloc, info) => {
607605
diag.arg("alloc", alloc);
608606
diag.arg("access", info.access);
609607
diag.arg("uninit", info.bad);

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tracing::trace;
1313

1414
use super::util::ensure_monomorphic_enough;
1515
use super::{
16-
FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub,
16+
FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok,
1717
throw_ub_custom,
1818
};
1919
use crate::fluent_generated as fluent;
@@ -212,14 +212,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
212212
assert!(src.layout.ty.is_raw_ptr());
213213
return match **src {
214214
Immediate::ScalarPair(data, _) => interp_ok(ImmTy::from_scalar(data, cast_to)),
215-
Immediate::Scalar(..) => span_bug!(
215+
Immediate::Scalar(..) | Immediate::Uninit => span_bug!(
216216
self.cur_span(),
217217
"{:?} input to a fat-to-thin cast ({} -> {})",
218218
*src,
219219
src.layout.ty,
220220
cast_to.ty
221221
),
222-
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
223222
};
224223
}
225224
}

compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use either::{Either, Left, Right};
77
use rustc_abi as abi;
88
use rustc_abi::{BackendRepr, HasDataLayout, Size};
99
use rustc_hir::def::Namespace;
10-
use rustc_middle::mir::interpret::{BadBytesAccess, ScalarSizeMismatch};
10+
use rustc_middle::mir::interpret::ScalarSizeMismatch;
1111
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
1212
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
1313
use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
@@ -663,15 +663,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
663663
}
664664
let imm = self.read_immediate_raw(op)?.right().unwrap();
665665
if matches!(*imm, Immediate::Uninit) {
666-
throw_ub!(InvalidUninitBytes(match op.to_op(self)?.as_mplace_or_imm() {
667-
Left(mplace) => mplace.ptr().provenance.and_then(|prov| {
668-
let start = mplace.ptr().into_parts().1;
669-
let size = op.layout().size;
670-
let range = alloc_range(start, size);
671-
Some((prov.get_alloc_id()?, BadBytesAccess { access: range, bad: range }))
672-
}),
673-
Right(_) => None,
674-
}))
666+
// The only other source of uninit immediates is locals, and those are only ever converted
667+
// to `Operand`s.
668+
span_bug!(
669+
self.tcx.span,
670+
"uninit immediate reads should have already errored when reading from memory"
671+
)
675672
}
676673
interp_ok(imm)
677674
}

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
397397
interp_ok(try_validation!(
398398
self.ecx.read_immediate(val),
399399
self.path,
400-
Ub(InvalidUninitBytes(_)) =>
400+
Ub(InvalidUninitBytes(..)) =>
401401
Uninit { expected },
402402
// The `Unsup` cases can only occur during CTFE
403403
Unsup(ReadPointerAsInt(_)) =>
@@ -1203,7 +1203,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
12031203
// For some errors we might be able to provide extra information.
12041204
// (This custom logic does not fit the `try_validation!` macro.)
12051205
match kind {
1206-
Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
1206+
Ub(InvalidUninitBytes(_alloc_id, access)) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
12071207
// Some byte was uninitialized, determine which
12081208
// element that byte belongs to so we can
12091209
// provide an index.
@@ -1213,7 +1213,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
12131213
.unwrap();
12141214
self.path.push(PathElem::ArrayElem(i));
12151215

1216-
if matches!(kind, Ub(InvalidUninitBytes(_))) {
1216+
if matches!(kind, Ub(InvalidUninitBytes(..))) {
12171217
err_validation_failure!(self.path, Uninit { expected })
12181218
} else {
12191219
err_validation_failure!(self.path, PointerAsInt { expected })

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ pub enum AllocError {
309309
/// Partially copying a pointer.
310310
ReadPartialPointer(Size),
311311
/// Using uninitialized data where it is not allowed.
312-
InvalidUninitBytes(Option<BadBytesAccess>),
312+
InvalidUninitBytes(BadBytesAccess),
313313
}
314314
pub type AllocResult<T = ()> = Result<T, AllocError>;
315315

@@ -336,7 +336,7 @@ impl AllocError {
336336
UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
337337
),
338338
InvalidUninitBytes(info) => InterpErrorKind::UndefinedBehavior(
339-
UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
339+
UndefinedBehaviorInfo::InvalidUninitBytes(alloc_id, info),
340340
),
341341
}
342342
}
@@ -597,10 +597,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
597597
range: AllocRange,
598598
) -> AllocResult<&[u8]> {
599599
self.init_mask.is_range_initialized(range).map_err(|uninit_range| {
600-
AllocError::InvalidUninitBytes(Some(BadBytesAccess {
601-
access: range,
602-
bad: uninit_range,
603-
}))
600+
AllocError::InvalidUninitBytes(BadBytesAccess { access: range, bad: uninit_range })
604601
})?;
605602
if !Prov::OFFSET_IS_ADDR && !self.provenance.range_empty(range, cx) {
606603
// Find the provenance.
@@ -701,10 +698,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
701698
) -> AllocResult<Scalar<Prov>> {
702699
// First and foremost, if anything is uninit, bail.
703700
if let Err(bad) = self.init_mask.is_range_initialized(range) {
704-
return Err(AllocError::InvalidUninitBytes(Some(BadBytesAccess {
705-
access: range,
706-
bad,
707-
})));
701+
return Err(AllocError::InvalidUninitBytes(BadBytesAccess { access: range, bad }));
708702
}
709703

710704
// Get the integer part of the result. We HAVE TO check provenance before returning this!

compiler/rustc_middle/src/mir/interpret/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ pub enum UndefinedBehaviorInfo<'tcx> {
412412
/// Using a string that is not valid UTF-8,
413413
InvalidStr(std::str::Utf8Error),
414414
/// Using uninitialized data where it is not allowed.
415-
InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
415+
InvalidUninitBytes(AllocId, BadBytesAccess),
416416
/// Working with a local that is not currently live.
417417
DeadLocal,
418418
/// Data size is not equal to target size.

src/tools/miri/src/concurrency/data_race.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,10 +731,9 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
731731
}
732732

733733
let scalar = this.allow_data_races_ref(move |this| this.read_scalar(place))?;
734-
let buffered_scalar = this.buffered_atomic_read(place, atomic, scalar, || {
734+
this.buffered_atomic_read(place, atomic, scalar, || {
735735
this.validate_atomic_load(place, atomic)
736-
})?;
737-
interp_ok(buffered_scalar.ok_or_else(|| err_ub!(InvalidUninitBytes(None)))?)
736+
})
738737
}
739738

740739
/// Perform an atomic write operation at the memory location.

src/tools/miri/src/concurrency/weak_memory.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
488488
atomic: AtomicReadOrd,
489489
latest_in_mo: Scalar,
490490
validate: impl FnOnce() -> InterpResult<'tcx>,
491-
) -> InterpResult<'tcx, Option<Scalar>> {
491+
) -> InterpResult<'tcx, Scalar> {
492492
let this = self.eval_context_ref();
493493
'fallback: {
494494
if let Some(global) = this.machine.data_race.as_vclocks_ref() {
@@ -518,15 +518,20 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
518518
ptr: place.ptr(),
519519
});
520520
}
521-
522-
return interp_ok(loaded);
521+
return interp_ok(loaded.ok_or_else(|| {
522+
let access = alloc_range(base_offset, place.layout.size);
523+
err_ub!(InvalidUninitBytes(
524+
alloc_id,
525+
BadBytesAccess { access, bad: access }
526+
))
527+
})?);
523528
}
524529
}
525530
}
526531

527532
// Race detector or weak memory disabled, simply read the latest value
528533
validate()?;
529-
interp_ok(Some(latest_in_mo))
534+
interp_ok(latest_in_mo)
530535
}
531536

532537
/// Add the given write to the store buffer. (Does not change machine memory.)

src/tools/miri/src/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ pub fn report_error<'tcx>(
411411
// Since `format_interp_error` consumes `e`, we compute the outut early.
412412
let mut extra = String::new();
413413
match e.kind() {
414-
UndefinedBehavior(InvalidUninitBytes(Some((alloc_id, access)))) => {
414+
UndefinedBehavior(InvalidUninitBytes(alloc_id, access)) => {
415415
writeln!(
416416
extra,
417417
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",

0 commit comments

Comments
 (0)