about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-11-22 17:38:59 +0100
committerRalf Jung <post@ralfj.de>2018-11-22 17:39:07 +0100
commitd9de72fcac7cfd90742a8fa8e4f6c0efd664ecde (patch)
tree622574250eb92c71b5536be33803bc527643b5e4
parente1ca4f63f4cee0c468325572b86f00badce70ad7 (diff)
downloadrust-d9de72fcac7cfd90742a8fa8e4f6c0efd664ecde.tar.gz
rust-d9de72fcac7cfd90742a8fa8e4f6c0efd664ecde.zip
miri: restrict fn argument punning to Rust ABI
-rw-r--r--src/librustc_mir/interpret/terminator.rs33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 44894656797..11c44fc943d 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -182,6 +182,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     }
 
     fn check_argument_compat(
+        rust_abi: bool,
         caller: TyLayout<'tcx>,
         callee: TyLayout<'tcx>,
     ) -> bool {
@@ -189,12 +190,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             // No question
             return true;
         }
+        if !rust_abi {
+            // Don't risk anything
+            return false;
+        }
         // Compare layout
         match (&caller.abi, &callee.abi) {
+            // Different valid ranges are okay (once we enforce validity,
+            // that will take care to make it UB to leave the range, just
+            // like for transmute).
             (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) =>
-                // Different valid ranges are okay (once we enforce validity,
-                // that will take care to make it UB to leave the range, just
-                // like for transmute).
                 caller.value == callee.value,
             (layout::Abi::ScalarPair(ref caller1, ref caller2),
              layout::Abi::ScalarPair(ref callee1, ref callee2)) =>
@@ -207,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     /// Pass a single argument, checking the types for compatibility.
     fn pass_argument(
         &mut self,
-        skip_zst: bool,
+        rust_abi: bool,
         caller_arg: &mut impl Iterator<Item=OpTy<'tcx, M::PointerTag>>,
         callee_arg: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
-        if skip_zst && callee_arg.layout.is_zst() {
+        if rust_abi && callee_arg.layout.is_zst() {
             // Nothing to do.
             trace!("Skipping callee ZST");
             return Ok(());
         }
         let caller_arg = caller_arg.next()
             .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
-        if skip_zst {
+        if rust_abi {
             debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
         }
         // Now, check
-        if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) {
+        if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
             return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
         }
         // We allow some transmutes here
@@ -322,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // Figure out how to pass which arguments.
                     // We have two iterators: Where the arguments come from,
                     // and where they go to.
-                    let skip_zst = match caller_abi {
+                    let rust_abi = match caller_abi {
                         Abi::Rust | Abi::RustCall => true,
                         _ => false
                     };
@@ -347,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                         };
                     // Skip ZSTs
                     let mut caller_iter = caller_args.iter()
-                        .filter(|op| !skip_zst || !op.layout.is_zst())
+                        .filter(|op| !rust_abi || !op.layout.is_zst())
                         .map(|op| *op);
 
                     // Now we have to spread them out across the callee's locals,
@@ -362,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                             // Must be a tuple
                             for i in 0..dest.layout.fields.count() {
                                 let dest = self.place_field(dest, i as u64)?;
-                                self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                                self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                             }
                         } else {
                             // Normal argument
-                            self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                            self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                         }
                     }
                     // Now we should have no more caller args
@@ -377,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // Don't forget to check the return type!
                     if let Some(caller_ret) = dest {
                         let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
-                        if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) {
+                        if !Self::check_argument_compat(
+                            rust_abi,
+                            caller_ret.layout,
+                            callee_ret.layout,
+                        ) {
                             return err!(FunctionRetMismatch(
                                 caller_ret.layout.ty, callee_ret.layout.ty
                             ));