]> git.lizzy.rs Git - rust.git/blobdiff - src/shims/mod.rs
avoid using unchecked casts or arithmetic
[rust.git] / src / shims / mod.rs
index 21e69dc1f0fc205f011bc670ec1f868496e63f88..d9e4d226ecc9a6d428751be0f3b08baf3c3f71e1 100644 (file)
@@ -1,13 +1,16 @@
 pub mod dlsym;
 pub mod env;
 pub mod foreign_items;
-pub mod intrinsics;
-pub mod tls;
 pub mod fs;
-pub mod time;
+pub mod intrinsics;
 pub mod panic;
+pub mod time;
+pub mod tls;
+
+use std::convert::TryFrom;
 
 use rustc::{mir, ty};
+
 use crate::*;
 
 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@@ -17,23 +20,14 @@ fn find_mir_or_eval_fn(
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Tag>],
         ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
-        unwind: Option<mir::BasicBlock>
+        unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
         let this = self.eval_context_mut();
-        trace!(
-            "eval_fn_call: {:#?}, {:?}",
-            instance,
-            ret.map(|p| *p.0)
-        );
+        trace!("eval_fn_call: {:#?}, {:?}", instance, ret.map(|p| *p.0));
 
         // There are some more lang items we want to hook that CTFE does not hook (yet).
         if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {
-            let (dest, ret) = ret.unwrap();
-            let n = this
-                .align_offset(args[0], args[1])?
-                .unwrap_or_else(|| this.truncate(u128::max_value(), dest.layout));
-            this.write_scalar(Scalar::from_uint(n, dest.layout.size), dest)?;
-            this.go_to_block(ret);
+            this.align_offset(args[0], args[1], ret, unwind)?;
             return Ok(None);
         }
 
@@ -49,41 +43,49 @@ fn find_mir_or_eval_fn(
         }
 
         // Otherwise, load the MIR.
-        Ok(Some(this.load_mir(instance.def, None)?.body()))
+        Ok(Some(&*this.load_mir(instance.def, None)?))
     }
 
     fn align_offset(
         &mut self,
         ptr_op: OpTy<'tcx, Tag>,
         align_op: OpTy<'tcx, Tag>,
-    ) -> InterpResult<'tcx, Option<u128>> {
+        ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
+        unwind: Option<mir::BasicBlock>,
+    ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
+        let (dest, ret) = ret.unwrap();
 
-        let req_align = this.force_bits(
-            this.read_scalar(align_op)?.not_undef()?,
-            this.pointer_size(),
-        )? as usize;
+        let req_align = this
+            .force_bits(this.read_scalar(align_op)?.not_undef()?, this.pointer_size())?;
 
-        // FIXME: This should actually panic in the interpreted program
+        // Stop if the alignment is not a power of two.
         if !req_align.is_power_of_two() {
-            throw_unsup_format!("Required alignment should always be a power of two")
+            return this.start_panic("align_offset: align is not a power-of-two", unwind);
         }
 
         let ptr_scalar = this.read_scalar(ptr_op)?.not_undef()?;
 
+        // Default: no result.
+        let mut result = this.truncate(u128::MAX, dest.layout);
         if let Ok(ptr) = this.force_ptr(ptr_scalar) {
-            let cur_align = this.memory.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)?.1.bytes() as usize;
-            if cur_align >= req_align {
-                // if the allocation alignment is at least the required alignment we use the
-                // libcore implementation
-                return Ok(Some(
+            // Only do anything if we can identify the allocation this goes to.
+            let cur_align =
+                this.memory.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)?.1.bytes();
+            if u128::from(cur_align) >= req_align {
+                // If the allocation alignment is at least the required alignment we use the
+                // libcore implementation.
+                // FIXME: is this correct in case of truncation?
+                result = u128::try_from(
                     (this.force_bits(ptr_scalar, this.pointer_size())? as *const i8)
-                        .align_offset(req_align) as u128,
-                ));
+                        .align_offset(usize::try_from(req_align).unwrap())
+                ).unwrap();
             }
         }
-        // If the allocation alignment is smaller than then required alignment or the pointer was
-        // actually an integer, we return `None`
-        Ok(None)
+
+        // Return result, and jump to caller.
+        this.write_scalar(Scalar::from_uint(result, dest.layout.size), dest)?;
+        this.go_to_block(ret);
+        Ok(())
     }
 }