]> git.lizzy.rs Git - rust.git/commitdiff
getting a path should never fail
authorRalf Jung <post@ralfj.de>
Mon, 9 Mar 2020 08:38:33 +0000 (09:38 +0100)
committerRalf Jung <post@ralfj.de>
Thu, 19 Mar 2020 07:26:08 +0000 (08:26 +0100)
we basically treat them as lang items

src/helpers.rs
src/shims/foreign_items.rs
src/shims/foreign_items/posix.rs
src/shims/foreign_items/posix/linux.rs
src/shims/fs.rs
src/shims/time.rs

index 43d9f1bf0b06dac495c26dd9c3447f36b4aebf87..169bb4205649eb348ba6a06d18c65ec7841acc83 100644 (file)
@@ -18,7 +18,7 @@
 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
 
 /// Gets an instance for a path.
-fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tcx, DefId> {
+fn try_resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> Option<DefId> {
     tcx.crates()
         .iter()
         .find(|&&krate| tcx.original_crate_name(krate).as_str() == path[0])
@@ -41,18 +41,47 @@ fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tc
             }
             None
         })
-        .ok_or_else(|| {
-            err_unsup_format!("failed to find required Rust item: {:?}", path).into()
-        })
 }
 
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
     /// Gets an instance for a path.
-    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
-        Ok(ty::Instance::mono(
-            self.eval_context_ref().tcx.tcx,
-            resolve_did(self.eval_context_ref().tcx.tcx, path)?,
-        ))
+    fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> {
+        let did = try_resolve_did(self.eval_context_ref().tcx.tcx, path)
+            .unwrap_or_else(|| panic!("failed to find required Rust item: {:?}", path));
+        ty::Instance::mono(self.eval_context_ref().tcx.tcx, did)
+    }
+
+    /// Evaluates the scalar at the specified path. Returns Some(val)
+    /// if the path could be resolved, and None otherwise
+    fn eval_path_scalar(
+        &mut self,
+        path: &[&str],
+    ) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>> {
+        let this = self.eval_context_mut();
+        let instance = this.resolve_path(path);
+        let cid = GlobalId { instance, promoted: None };
+        let const_val = this.const_eval_raw(cid)?;
+        let const_val = this.read_scalar(const_val.into())?;
+        return Ok(const_val);
+    }
+
+    /// Helper function to get a `libc` constant as a `Scalar`.
+    fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
+        self.eval_context_mut()
+            .eval_path_scalar(&["libc", name])?
+            .not_undef()
+    }
+
+    /// Helper function to get a `libc` constant as an `i32`.
+    fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
+        self.eval_libc(name)?.to_i32()
+    }
+
+    /// Helper function to get the `TyLayout` of a `libc` type
+    fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
+        let this = self.eval_context_mut();
+        let ty = this.resolve_path(&["libc", name]).monomorphic_ty(*this.tcx);
+        this.layout_of(ty)
     }
 
     /// Write a 0 of the appropriate size to `dest`.
@@ -97,7 +126,7 @@ fn gen_random(&mut self, ptr: Scalar<Tag>, len: u64) -> InterpResult<'tcx> {
         if this.machine.communicate {
             // Fill the buffer using the host's rng.
             getrandom::getrandom(&mut data)
-                .map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
+                .map_err(|err| err_unsup_format!("host getrandom failed: {}", err))?;
         } else {
             let rng = this.memory.extra.rng.get_mut();
             rng.fill_bytes(&mut data);
@@ -312,26 +341,6 @@ fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>, fields: usize) -> InterpResult
         }
     }
 
-    /// Helper function to get a `libc` constant as a `Scalar`.
-    fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
-        self.eval_context_mut()
-            .eval_path_scalar(&["libc", name])?
-            .ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
-            .not_undef()
-    }
-
-    /// Helper function to get a `libc` constant as an `i32`.
-    fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
-        self.eval_libc(name)?.to_i32()
-    }
-
-    /// Helper function to get the `TyLayout` of a `libc` type
-    fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
-        let this = self.eval_context_mut();
-        let ty = this.resolve_path(&["libc", name])?.monomorphic_ty(*this.tcx);
-        this.layout_of(ty)
-    }
-
     // Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
     // different values into a struct.
     fn write_packed_immediates(
@@ -530,7 +539,7 @@ pub fn immty_from_int_checked<'tcx>(
 ) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
     let int = int.into();
     Ok(ImmTy::try_from_int(int, layout).ok_or_else(|| {
-        err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
+        err_unsup_format!("signed value {:#x} does not fit in {} bits", int, layout.size.bits())
     })?)
 }
 
@@ -540,6 +549,6 @@ pub fn immty_from_uint_checked<'tcx>(
 ) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
     let int = int.into();
     Ok(ImmTy::try_from_uint(int, layout).ok_or_else(|| {
-        err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
+        err_unsup_format!("unsigned value {:#x} does not fit in {} bits", int, layout.size.bits())
     })?)
 }
index b4931d36004444f20f79359d90b86b4d296c4fa7..fab90e3cc5291a5a0a8323813f68004b956b755c 100644 (file)
@@ -165,7 +165,7 @@ fn emulate_foreign_item(
                     .expect("No panic runtime found!");
                 let panic_runtime = tcx.crate_name(*panic_runtime);
                 let start_panic_instance =
-                    this.resolve_path(&[&*panic_runtime.as_str(), link_name])?;
+                    this.resolve_path(&[&*panic_runtime.as_str(), link_name]);
                 return Ok(Some(&*this.load_mir(start_panic_instance.def, None)?));
             }
             _ => {}
@@ -454,20 +454,4 @@ fn check_alloc_request(size: u64, align: u64) -> InterpResult<'tcx> {
         }
         Ok(())
     }
-
-    /// Evaluates the scalar at the specified path. Returns Some(val)
-    /// if the path could be resolved, and None otherwise
-    fn eval_path_scalar(
-        &mut self,
-        path: &[&str],
-    ) -> InterpResult<'tcx, Option<ScalarMaybeUndef<Tag>>> {
-        let this = self.eval_context_mut();
-        if let Ok(instance) = this.resolve_path(path) {
-            let cid = GlobalId { instance, promoted: None };
-            let const_val = this.const_eval_raw(cid)?;
-            let const_val = this.read_scalar(const_val.into())?;
-            return Ok(Some(const_val));
-        }
-        return Ok(None);
-    }
 }
index b9449c2653d623f17157c582964bdaca9133851d..85e9b88b6ec03db7b96c8127a578daa6c604df67 100644 (file)
@@ -289,22 +289,17 @@ fn emulate_foreign_item_by_name(
 
                 trace!("sysconf() called with name {}", name);
                 // TODO: Cache the sysconf integers via Miri's global cache.
-                let paths = &[
-                    (&["libc", "_SC_PAGESIZE"], Scalar::from_int(PAGE_SIZE, dest.layout.size)),
-                    (&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_int(-1, dest.layout.size)),
-                    (
-                        &["libc", "_SC_NPROCESSORS_ONLN"],
-                        Scalar::from_int(NUM_CPUS, dest.layout.size),
-                    ),
+                let sysconfs = &[
+                    ("_SC_PAGESIZE", Scalar::from_int(PAGE_SIZE, dest.layout.size)),
+                    ("_SC_GETPW_R_SIZE_MAX", Scalar::from_int(-1, dest.layout.size)),
+                    ("_SC_NPROCESSORS_ONLN", Scalar::from_int(NUM_CPUS, dest.layout.size)),
                 ];
                 let mut result = None;
-                for &(path, path_value) in paths {
-                    if let Some(val) = this.eval_path_scalar(path)? {
-                        let val = val.to_i32()?;
-                        if val == name {
-                            result = Some(path_value);
-                            break;
-                        }
+                for &(sysconf_name, value) in sysconfs {
+                    let sysconf_name = this.eval_libc_i32(sysconf_name)?;
+                    if sysconf_name == name {
+                        result = Some(value);
+                        break;
                     }
                 }
                 if let Some(result) = result {
index 023fee4ca7b1eef68bc37bed701bb41680e52751..82928c9bc17ff045011a2cf7949579727ffbb429 100644 (file)
@@ -56,13 +56,11 @@ fn emulate_foreign_item_by_name(
 
             "syscall" => {
                 let sys_getrandom = this
-                    .eval_path_scalar(&["libc", "SYS_getrandom"])?
-                    .expect("Failed to get libc::SYS_getrandom")
+                    .eval_libc("SYS_getrandom")?
                     .to_machine_usize(this)?;
 
                 let sys_statx = this
-                    .eval_path_scalar(&["libc", "SYS_statx"])?
-                    .expect("Failed to get libc::SYS_statx")
+                    .eval_libc("SYS_statx")?
                     .to_machine_usize(this)?;
 
                 match this.read_scalar(args[0])?.to_machine_usize(this)? {
index 6894647de44da6ab65b2874e6abd6733eab6f533..cb429109a4a50b4c94c679f9eb5c65e5767d7b96 100644 (file)
@@ -643,7 +643,7 @@ fn linux_statx(
             // FIXME: This long path is required because `libc::statx` is an struct and also a
             // function and `resolve_path` is returning the latter.
             let statx_ty = this
-                .resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])?
+                .resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])
                 .monomorphic_ty(*this.tcx);
             let statxbuf_ty = this.tcx.mk_mut_ptr(statx_ty);
             let statxbuf_layout = this.layout_of(statxbuf_ty)?;
@@ -655,13 +655,13 @@ fn linux_statx(
         // `flags` should be a `c_int` but the `syscall` function provides an `isize`.
         let flags: i32 =
             this.read_scalar(flags_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
-                err_unsup_format!("Failed to convert pointer sized operand to integer: {}", e)
+                err_unsup_format!("failed to convert pointer sized operand to integer: {}", e)
             })?;
         let empty_path_flag = flags & this.eval_libc("AT_EMPTY_PATH")?.to_i32()? != 0;
         // `dirfd` should be a `c_int` but the `syscall` function provides an `isize`.
         let dirfd: i32 =
             this.read_scalar(dirfd_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
-                err_unsup_format!("Failed to convert pointer sized operand to integer: {}", e)
+                err_unsup_format!("failed to convert pointer sized operand to integer: {}", e)
             })?;
         // We only support:
         // * interpreting `path` as an absolute directory,
@@ -676,7 +676,7 @@ fn linux_statx(
             (path.as_os_str().is_empty() && empty_path_flag)
         ) {
             throw_unsup_format!(
-                "Using statx is only supported with absolute paths, relative paths with the file \
+                "using statx is only supported with absolute paths, relative paths with the file \
                 descriptor `AT_FDCWD`, and empty paths with the `AT_EMPTY_PATH` flag set and any \
                 file descriptor"
             )
@@ -886,7 +886,7 @@ fn linux_readdir64_r(
         let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
 
         let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
-            err_unsup_format!("The DIR pointer passed to readdir64_r did not come from opendir")
+            err_unsup_format!("the DIR pointer passed to readdir64_r did not come from opendir")
         })?;
         match dir_iter.next() {
             Some(Ok(dir_entry)) => {
@@ -973,7 +973,7 @@ fn macos_readdir_r(
         let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
 
         let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
-            err_unsup_format!("The DIR pointer passed to readdir_r did not come from opendir")
+            err_unsup_format!("the DIR pointer passed to readdir_r did not come from opendir")
         })?;
         match dir_iter.next() {
             Some(Ok(dir_entry)) => {
index d761698e0d27807e17756e05eeb53389959031fe..627478eaaab70d871243f9d2b7203dfd5686c379 100644 (file)
@@ -12,7 +12,7 @@ fn get_time<'tcx>() -> InterpResult<'tcx, Duration> {
 /// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
 pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
     time.duration_since(SystemTime::UNIX_EPOCH)
-        .map_err(|_| err_unsup_format!("Times before the Unix epoch are not supported").into())
+        .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
 }
 
 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}