expose host-to-target path conversion to interpreted program
This commit is contained in:
parent
f2ae9e580a
commit
c19ca083ee
5 changed files with 78 additions and 36 deletions
|
|
@ -576,6 +576,21 @@ extern "Rust" {
|
|||
|
||||
/// Miri-provided extern function to deallocate memory.
|
||||
fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||
|
||||
/// Convert a path from the host Miri runs on to the target Miri interprets.
|
||||
/// Performs conversion of path separators as needed.
|
||||
///
|
||||
/// Usually Miri performs this kind of conversion automatically. However, manual conversion
|
||||
/// might be necessary when reading an environment variable that was set of the host
|
||||
/// (such as TMPDIR) and using it as a target path.
|
||||
///
|
||||
/// Only works with isolation disabled.
|
||||
///
|
||||
/// `in` must point to a null-terminated string, and will be read as the input host path.
|
||||
/// `out` must point to at least `out_size` many bytes, and the result will be stored there
|
||||
/// with a null terminator.
|
||||
/// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
|
||||
fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::hash_map::Entry, io::Write, iter};
|
||||
use std::{collections::hash_map::Entry, io::Write, iter, path::Path};
|
||||
|
||||
use log::trace;
|
||||
|
||||
|
|
@ -442,6 +442,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
}
|
||||
this.machine.static_roots.push(alloc_id);
|
||||
}
|
||||
"miri_host_to_target_path" => {
|
||||
let [ptr, out, out_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let out = this.read_pointer(out)?;
|
||||
let out_size = this.read_scalar(out_size)?.to_machine_usize(this)?;
|
||||
|
||||
// The host affects program behavior here, so this requires isolation to be disabled.
|
||||
this.check_no_isolation("`miri_host_to_target_path`")?;
|
||||
|
||||
// We read this as a plain OsStr and write it as a path, which will convert it to the target.
|
||||
let path = this.read_os_str_from_c_str(ptr)?.to_owned();
|
||||
let (success, needed_size) = this.write_path_to_c_str(Path::new(&path), out, out_size)?;
|
||||
// Return value: 0 on success, otherwise the size it would have needed.
|
||||
this.write_int(if success { 0 } else { needed_size }, dest)?;
|
||||
}
|
||||
|
||||
// Obtains the size of a Miri backtrace. See the README for details.
|
||||
"miri_backtrace_size" => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#![feature(io_error_uncategorized)]
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs::{canonicalize, remove_dir_all, remove_file, File};
|
||||
use std::io::{Error, ErrorKind, Write};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
|
@ -23,20 +23,21 @@ fn main() {
|
|||
}
|
||||
|
||||
fn tmp() -> PathBuf {
|
||||
std::env::var("MIRI_TEMP")
|
||||
.map(|tmp| {
|
||||
// MIRI_TEMP is set outside of our emulated
|
||||
// program, so it may have path separators that don't
|
||||
// correspond to our target platform. We normalize them here
|
||||
// before constructing a `PathBuf`
|
||||
let path = std::env::var("MIRI_TEMP")
|
||||
.unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
|
||||
// These are host paths. We need to convert them to the target.
|
||||
let path = CString::new(path).unwrap();
|
||||
let mut out = Vec::with_capacity(1024);
|
||||
|
||||
#[cfg(windows)]
|
||||
return PathBuf::from(tmp.replace("/", "\\"));
|
||||
|
||||
#[cfg(not(windows))]
|
||||
return PathBuf::from(tmp.replace("\\", "/"));
|
||||
})
|
||||
.unwrap_or_else(|_| std::env::temp_dir())
|
||||
unsafe {
|
||||
extern "Rust" {
|
||||
fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
|
||||
}
|
||||
let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
|
||||
assert_eq!(ret, 0);
|
||||
let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
|
||||
PathBuf::from(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare: compute filename and make sure the file does not exist.
|
||||
|
|
|
|||
|
|
@ -7,15 +7,23 @@ use std::os::unix::io::AsRawFd;
|
|||
use std::path::PathBuf;
|
||||
|
||||
fn tmp() -> PathBuf {
|
||||
std::env::var("MIRI_TEMP")
|
||||
.map(|tmp| {
|
||||
// MIRI_TEMP is set outside of our emulated
|
||||
// program, so it may have path separators that don't
|
||||
// correspond to our target platform. We normalize them here
|
||||
// before constructing a `PathBuf`
|
||||
return PathBuf::from(tmp.replace("\\", "/"));
|
||||
})
|
||||
.unwrap_or_else(|_| std::env::temp_dir())
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
let path = std::env::var("MIRI_TEMP")
|
||||
.unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
|
||||
// These are host paths. We need to convert them to the target.
|
||||
let path = CString::new(path).unwrap();
|
||||
let mut out = Vec::with_capacity(1024);
|
||||
|
||||
unsafe {
|
||||
extern "Rust" {
|
||||
fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
|
||||
}
|
||||
let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
|
||||
assert_eq!(ret, 0);
|
||||
let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
|
||||
PathBuf::from(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Test allocating variant of `realpath`.
|
||||
|
|
|
|||
|
|
@ -31,20 +31,23 @@ fn main() {
|
|||
}
|
||||
|
||||
fn tmp() -> PathBuf {
|
||||
std::env::var("MIRI_TEMP")
|
||||
.map(|tmp| {
|
||||
// MIRI_TEMP is set outside of our emulated
|
||||
// program, so it may have path separators that don't
|
||||
// correspond to our target platform. We normalize them here
|
||||
// before constructing a `PathBuf`
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
#[cfg(windows)]
|
||||
return PathBuf::from(tmp.replace("/", "\\"));
|
||||
let path = std::env::var("MIRI_TEMP")
|
||||
.unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
|
||||
// These are host paths. We need to convert them to the target.
|
||||
let path = CString::new(path).unwrap();
|
||||
let mut out = Vec::with_capacity(1024);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
return PathBuf::from(tmp.replace("\\", "/"));
|
||||
})
|
||||
.unwrap_or_else(|_| std::env::temp_dir())
|
||||
unsafe {
|
||||
extern "Rust" {
|
||||
fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
|
||||
}
|
||||
let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
|
||||
assert_eq!(ret, 0);
|
||||
let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
|
||||
PathBuf::from(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare: compute filename and make sure the file does not exist.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue