From: Ralf Jung Date: Mon, 9 Mar 2020 08:38:33 +0000 (+0100) Subject: getting a path should never fail X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=681819c8ad2a33923a33fc6829cfd588eb1f721f;p=rust.git getting a path should never fail we basically treat them as lang items --- diff --git a/src/helpers.rs b/src/helpers.rs index 43d9f1bf0b0..169bb420564 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -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 { 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> { + 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> { + 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, 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> { - 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()) })?) } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index b4931d36004..fab90e3cc52 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -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>> { - 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); - } } diff --git a/src/shims/foreign_items/posix.rs b/src/shims/foreign_items/posix.rs index b9449c2653d..85e9b88b6ec 100644 --- a/src/shims/foreign_items/posix.rs +++ b/src/shims/foreign_items/posix.rs @@ -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 { diff --git a/src/shims/foreign_items/posix/linux.rs b/src/shims/foreign_items/posix/linux.rs index 023fee4ca7b..82928c9bc17 100644 --- a/src/shims/foreign_items/posix/linux.rs +++ b/src/shims/foreign_items/posix/linux.rs @@ -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)? { diff --git a/src/shims/fs.rs b/src/shims/fs.rs index 6894647de44..cb429109a4a 100644 --- a/src/shims/fs.rs +++ b/src/shims/fs.rs @@ -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)) => { diff --git a/src/shims/time.rs b/src/shims/time.rs index d761698e0d2..627478eaaab 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -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> {}