about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2020-10-18 16:32:25 -0400
committerWesley Wiser <wwiser@gmail.com>2020-10-24 16:00:04 -0400
commitdd683e5ab5d79782a484d919bb8de89764cf98d2 (patch)
tree1b3ada1c8ea4b0027d37858db469dab048917f01
parent89fdb30892dbe330730ad1a1c1fe45b9046c2973 (diff)
downloadrust-dd683e5ab5d79782a484d919bb8de89764cf98d2.tar.gz
rust-dd683e5ab5d79782a484d919bb8de89764cf98d2.zip
MIR validation should check `SwitchInt` values are valid for the type
-rw-r--r--compiler/rustc_mir/src/transform/validate.rs26
1 files changed, 24 insertions, 2 deletions
diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs
index beffffa727e..7b22d643ab6 100644
--- a/compiler/rustc_mir/src/transform/validate.rs
+++ b/compiler/rustc_mir/src/transform/validate.rs
@@ -5,13 +5,17 @@ use crate::dataflow::{Analysis, ResultsCursor};
 use crate::util::storage::AlwaysLiveLocals;
 
 use super::MirPass;
-use rustc_middle::mir::visit::{PlaceContext, Visitor};
+use rustc_middle::mir::{
+    interpret::Scalar,
+    visit::{PlaceContext, Visitor},
+};
 use rustc_middle::mir::{
     AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue,
     SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
 };
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
+use rustc_target::abi::Size;
 
 #[derive(Copy, Clone, Debug)]
 enum EdgeKind {
@@ -346,7 +350,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         ),
                     );
                 }
-                for (_, target) in targets.iter() {
+
+                let target_width = self.tcx.sess.target.pointer_width;
+
+                let size = Size::from_bits(match switch_ty.kind() {
+                    ty::Uint(uint) => uint.normalize(target_width).bit_width().unwrap(),
+                    ty::Int(int) => int.normalize(target_width).bit_width().unwrap(),
+                    ty::Char => 32,
+                    ty::Bool => 1,
+                    other => bug!("unhandled type: {:?}", other),
+                });
+
+                for (value, target) in targets.iter() {
+                    if Scalar::<()>::try_from_uint(value, size).is_none() {
+                        self.fail(
+                            location,
+                            format!("the value {:#x} is not a proper {:?}", value, switch_ty),
+                        )
+                    }
+
                     self.check_edge(location, target, EdgeKind::Normal);
                 }
                 self.check_edge(location, targets.otherwise(), EdgeKind::Normal);