Skip to content

Commit b6ab1fa

Browse files
committed
Auto merge of #95707 - RalfJung:initialized, r=oli-obk
interp/validity: enforce Scalar::Initialized This is a follow-up to #94527, to also account for the new kind of `Scalar` layout inside the validity checker. r? `@oli-obk`
2 parents 201cf3d + d214b38 commit b6ab1fa

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

compiler/rustc_const_eval/src/interpret/validity.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -629,11 +629,24 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
629629
op: &OpTy<'tcx, M::PointerTag>,
630630
scalar_layout: ScalarAbi,
631631
) -> InterpResult<'tcx> {
632-
if scalar_layout.valid_range(self.ecx).is_full_for(op.layout.size) {
632+
// We check `is_full_range` in a slightly complicated way because *if* we are checking
633+
// number validity, then we want to ensure that `Scalar::Initialized` is indeed initialized,
634+
// i.e. that we go over the `check_init` below.
635+
let is_full_range = match scalar_layout {
636+
ScalarAbi::Initialized { valid_range, .. } => {
637+
if M::enforce_number_validity(self.ecx) {
638+
false // not "full" since uninit is not accepted
639+
} else {
640+
valid_range.is_full_for(op.layout.size)
641+
}
642+
}
643+
ScalarAbi::Union { .. } => true,
644+
};
645+
if is_full_range {
633646
// Nothing to check
634647
return Ok(());
635648
}
636-
// At least one value is excluded.
649+
// We have something to check.
637650
let valid_range = scalar_layout.valid_range(self.ecx);
638651
let WrappingRange { start, end } = valid_range;
639652
let max_value = op.layout.size.unsigned_int_max();
@@ -647,9 +660,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
647660
expected { "something {}", wrapping_range_format(valid_range, max_value) },
648661
);
649662
let bits = match value.try_to_int() {
663+
Ok(int) => int.assert_bits(op.layout.size),
650664
Err(_) => {
651665
// So this is a pointer then, and casting to an int failed.
652666
// Can only happen during CTFE.
667+
// We support 2 kinds of ranges here: full range, and excluding zero.
653668
if start == 1 && end == max_value {
654669
// Only null is the niche. So make sure the ptr is NOT null.
655670
if self.ecx.scalar_may_be_null(value) {
@@ -660,7 +675,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
660675
wrapping_range_format(valid_range, max_value)
661676
}
662677
)
678+
} else {
679+
return Ok(());
663680
}
681+
} else if scalar_layout.valid_range(self.ecx).is_full_for(op.layout.size) {
682+
// Easy. (This is reachable if `enforce_number_validity` is set.)
664683
return Ok(());
665684
} else {
666685
// Conservatively, we reject, because the pointer *could* have a bad
@@ -674,9 +693,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
674693
)
675694
}
676695
}
677-
Ok(int) => int.assert_bits(op.layout.size),
678696
};
679-
// Now compare. This is slightly subtle because this is a special "wrap-around" range.
697+
// Now compare.
680698
if valid_range.contains(bits) {
681699
Ok(())
682700
} else {

0 commit comments

Comments
 (0)