Skip to content

Commit dd683e5

Browse files
committed
MIR validation should check SwitchInt values are valid for the type
1 parent 89fdb30 commit dd683e5

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

compiler/rustc_mir/src/transform/validate.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ use crate::dataflow::{Analysis, ResultsCursor};
55
use crate::util::storage::AlwaysLiveLocals;
66

77
use super::MirPass;
8-
use rustc_middle::mir::visit::{PlaceContext, Visitor};
8+
use rustc_middle::mir::{
9+
interpret::Scalar,
10+
visit::{PlaceContext, Visitor},
11+
};
912
use rustc_middle::mir::{
1013
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue,
1114
SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
1215
};
1316
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
1417
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
18+
use rustc_target::abi::Size;
1519

1620
#[derive(Copy, Clone, Debug)]
1721
enum EdgeKind {
@@ -346,7 +350,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
346350
),
347351
);
348352
}
349-
for (_, target) in targets.iter() {
353+
354+
let target_width = self.tcx.sess.target.pointer_width;
355+
356+
let size = Size::from_bits(match switch_ty.kind() {
357+
ty::Uint(uint) => uint.normalize(target_width).bit_width().unwrap(),
358+
ty::Int(int) => int.normalize(target_width).bit_width().unwrap(),
359+
ty::Char => 32,
360+
ty::Bool => 1,
361+
other => bug!("unhandled type: {:?}", other),
362+
});
363+
364+
for (value, target) in targets.iter() {
365+
if Scalar::<()>::try_from_uint(value, size).is_none() {
366+
self.fail(
367+
location,
368+
format!("the value {:#x} is not a proper {:?}", value, switch_ty),
369+
)
370+
}
371+
350372
self.check_edge(location, target, EdgeKind::Normal);
351373
}
352374
self.check_edge(location, targets.otherwise(), EdgeKind::Normal);

0 commit comments

Comments
 (0)