Skip to content

Commit fc27267

Browse files
committed
getting a path should never fail
we basically treat them as lang items
1 parent 03661b1 commit fc27267

File tree

6 files changed

+60
-74
lines changed

6 files changed

+60
-74
lines changed

src/helpers.rs

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::*;
1717
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
1818

1919
/// Gets an instance for a path.
20-
fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tcx, DefId> {
20+
fn try_resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> Option<DefId> {
2121
tcx.crates()
2222
.iter()
2323
.find(|&&krate| tcx.original_crate_name(krate).as_str() == path[0])
@@ -40,18 +40,47 @@ fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tc
4040
}
4141
None
4242
})
43-
.ok_or_else(|| {
44-
err_unsup_format!("failed to find required Rust item: {:?}", path).into()
45-
})
4643
}
4744

4845
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
4946
/// Gets an instance for a path.
50-
fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
51-
Ok(ty::Instance::mono(
52-
self.eval_context_ref().tcx.tcx,
53-
resolve_did(self.eval_context_ref().tcx.tcx, path)?,
54-
))
47+
fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> {
48+
let did = try_resolve_did(self.eval_context_ref().tcx.tcx, path)
49+
.unwrap_or_else(|| panic!("failed to find required Rust item: {:?}", path));
50+
ty::Instance::mono(self.eval_context_ref().tcx.tcx, did)
51+
}
52+
53+
/// Evaluates the scalar at the specified path. Returns Some(val)
54+
/// if the path could be resolved, and None otherwise
55+
fn eval_path_scalar(
56+
&mut self,
57+
path: &[&str],
58+
) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>> {
59+
let this = self.eval_context_mut();
60+
let instance = this.resolve_path(path);
61+
let cid = GlobalId { instance, promoted: None };
62+
let const_val = this.const_eval_raw(cid)?;
63+
let const_val = this.read_scalar(const_val.into())?;
64+
return Ok(const_val);
65+
}
66+
67+
/// Helper function to get a `libc` constant as a `Scalar`.
68+
fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
69+
self.eval_context_mut()
70+
.eval_path_scalar(&["libc", name])?
71+
.not_undef()
72+
}
73+
74+
/// Helper function to get a `libc` constant as an `i32`.
75+
fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
76+
self.eval_libc(name)?.to_i32()
77+
}
78+
79+
/// Helper function to get the `TyLayout` of a `libc` type
80+
fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
81+
let this = self.eval_context_mut();
82+
let ty = this.resolve_path(&["libc", name]).monomorphic_ty(*this.tcx);
83+
this.layout_of(ty)
5584
}
5685

5786
/// Write a 0 of the appropriate size to `dest`.
@@ -96,7 +125,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
96125
if this.machine.communicate {
97126
// Fill the buffer using the host's rng.
98127
getrandom::getrandom(&mut data)
99-
.map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
128+
.map_err(|err| err_unsup_format!("host getrandom failed: {}", err))?;
100129
} else {
101130
let rng = this.memory.extra.rng.get_mut();
102131
rng.fill_bytes(&mut data);
@@ -311,26 +340,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
311340
}
312341
}
313342

314-
/// Helper function to get a `libc` constant as a `Scalar`.
315-
fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
316-
self.eval_context_mut()
317-
.eval_path_scalar(&["libc", name])?
318-
.ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
319-
.not_undef()
320-
}
321-
322-
/// Helper function to get a `libc` constant as an `i32`.
323-
fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
324-
self.eval_libc(name)?.to_i32()
325-
}
326-
327-
/// Helper function to get the `TyLayout` of a `libc` type
328-
fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
329-
let this = self.eval_context_mut();
330-
let ty = this.resolve_path(&["libc", name])?.monomorphic_ty(*this.tcx);
331-
this.layout_of(ty)
332-
}
333-
334343
// Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
335344
// different values into a struct.
336345
fn write_packed_immediates(
@@ -529,7 +538,7 @@ pub fn immty_from_int_checked<'tcx>(
529538
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
530539
let int = int.into();
531540
Ok(ImmTy::try_from_int(int, layout).ok_or_else(|| {
532-
err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
541+
err_unsup_format!("signed value {:#x} does not fit in {} bits", int, layout.size.bits())
533542
})?)
534543
}
535544

@@ -539,6 +548,6 @@ pub fn immty_from_uint_checked<'tcx>(
539548
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
540549
let int = int.into();
541550
Ok(ImmTy::try_from_uint(int, layout).ok_or_else(|| {
542-
err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
551+
err_unsup_format!("unsigned value {:#x} does not fit in {} bits", int, layout.size.bits())
543552
})?)
544553
}

src/shims/foreign_items.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
142142
.expect("No panic runtime found!");
143143
let panic_runtime = tcx.crate_name(*panic_runtime);
144144
let start_panic_instance =
145-
this.resolve_path(&[&*panic_runtime.as_str(), "__rust_start_panic"])?;
145+
this.resolve_path(&[&*panic_runtime.as_str(), "__rust_start_panic"]);
146146
return Ok(Some(&*this.load_mir(start_panic_instance.def, None)?));
147147
}
148148
// Similarly, we forward calls to the `panic_impl` foreign item to its implementation.
@@ -457,20 +457,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
457457
}
458458
Ok(())
459459
}
460-
461-
/// Evaluates the scalar at the specified path. Returns Some(val)
462-
/// if the path could be resolved, and None otherwise
463-
fn eval_path_scalar(
464-
&mut self,
465-
path: &[&str],
466-
) -> InterpResult<'tcx, Option<ScalarMaybeUndef<Tag>>> {
467-
let this = self.eval_context_mut();
468-
if let Ok(instance) = this.resolve_path(path) {
469-
let cid = GlobalId { instance, promoted: None };
470-
let const_val = this.const_eval_raw(cid)?;
471-
let const_val = this.read_scalar(const_val.into())?;
472-
return Ok(Some(const_val));
473-
}
474-
return Ok(None);
475-
}
476460
}

src/shims/foreign_items/posix.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -287,22 +287,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
287287

288288
trace!("sysconf() called with name {}", name);
289289
// TODO: Cache the sysconf integers via Miri's global cache.
290-
let paths = &[
291-
(&["libc", "_SC_PAGESIZE"], Scalar::from_int(PAGE_SIZE, dest.layout.size)),
292-
(&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_int(-1, dest.layout.size)),
293-
(
294-
&["libc", "_SC_NPROCESSORS_ONLN"],
295-
Scalar::from_int(NUM_CPUS, dest.layout.size),
296-
),
290+
let sysconfs = &[
291+
("_SC_PAGESIZE", Scalar::from_int(PAGE_SIZE, dest.layout.size)),
292+
("_SC_GETPW_R_SIZE_MAX", Scalar::from_int(-1, dest.layout.size)),
293+
("_SC_NPROCESSORS_ONLN", Scalar::from_int(NUM_CPUS, dest.layout.size)),
297294
];
298295
let mut result = None;
299-
for &(path, path_value) in paths {
300-
if let Some(val) = this.eval_path_scalar(path)? {
301-
let val = val.to_i32()?;
302-
if val == name {
303-
result = Some(path_value);
304-
break;
305-
}
296+
for &(sysconf_name, value) in sysconfs {
297+
let sysconf_name = this.eval_libc_i32(sysconf_name)?;
298+
if sysconf_name == name {
299+
result = Some(value);
300+
break;
306301
}
307302
}
308303
if let Some(result) = result {

src/shims/foreign_items/posix/linux.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5656

5757
"syscall" => {
5858
let sys_getrandom = this
59-
.eval_path_scalar(&["libc", "SYS_getrandom"])?
60-
.expect("Failed to get libc::SYS_getrandom")
59+
.eval_libc("SYS_getrandom")?
6160
.to_machine_usize(this)?;
6261

6362
let sys_statx = this
64-
.eval_path_scalar(&["libc", "SYS_statx"])?
65-
.expect("Failed to get libc::SYS_statx")
63+
.eval_libc("SYS_statx")?
6664
.to_machine_usize(this)?;
6765

6866
match this.read_scalar(args[0])?.to_machine_usize(this)? {

src/shims/fs.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
643643
// FIXME: This long path is required because `libc::statx` is an struct and also a
644644
// function and `resolve_path` is returning the latter.
645645
let statx_ty = this
646-
.resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])?
646+
.resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])
647647
.monomorphic_ty(*this.tcx);
648648
let statxbuf_ty = this.tcx.mk_mut_ptr(statx_ty);
649649
let statxbuf_layout = this.layout_of(statxbuf_ty)?;
@@ -655,13 +655,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
655655
// `flags` should be a `c_int` but the `syscall` function provides an `isize`.
656656
let flags: i32 =
657657
this.read_scalar(flags_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
658-
err_unsup_format!("Failed to convert pointer sized operand to integer: {}", e)
658+
err_unsup_format!("failed to convert pointer sized operand to integer: {}", e)
659659
})?;
660660
let empty_path_flag = flags & this.eval_libc("AT_EMPTY_PATH")?.to_i32()? != 0;
661661
// `dirfd` should be a `c_int` but the `syscall` function provides an `isize`.
662662
let dirfd: i32 =
663663
this.read_scalar(dirfd_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
664-
err_unsup_format!("Failed to convert pointer sized operand to integer: {}", e)
664+
err_unsup_format!("failed to convert pointer sized operand to integer: {}", e)
665665
})?;
666666
// We only support:
667667
// * interpreting `path` as an absolute directory,
@@ -676,7 +676,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
676676
(path.as_os_str().is_empty() && empty_path_flag)
677677
) {
678678
throw_unsup_format!(
679-
"Using statx is only supported with absolute paths, relative paths with the file \
679+
"using statx is only supported with absolute paths, relative paths with the file \
680680
descriptor `AT_FDCWD`, and empty paths with the `AT_EMPTY_PATH` flag set and any \
681681
file descriptor"
682682
)
@@ -886,7 +886,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
886886
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
887887

888888
let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
889-
err_unsup_format!("The DIR pointer passed to readdir64_r did not come from opendir")
889+
err_unsup_format!("the DIR pointer passed to readdir64_r did not come from opendir")
890890
})?;
891891
match dir_iter.next() {
892892
Some(Ok(dir_entry)) => {
@@ -973,7 +973,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
973973
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
974974

975975
let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
976-
err_unsup_format!("The DIR pointer passed to readdir_r did not come from opendir")
976+
err_unsup_format!("the DIR pointer passed to readdir_r did not come from opendir")
977977
})?;
978978
match dir_iter.next() {
979979
Some(Ok(dir_entry)) => {

src/shims/time.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn get_time<'tcx>() -> InterpResult<'tcx, Duration> {
1212
/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
1313
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
1414
time.duration_since(SystemTime::UNIX_EPOCH)
15-
.map_err(|_| err_unsup_format!("Times before the Unix epoch are not supported").into())
15+
.map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
1616
}
1717

1818
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

0 commit comments

Comments
 (0)