diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index ce2b0143b5..7a54cde7e1 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -585,8 +585,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ); }; - if mode != 0o666 { - throw_unsup_format!("non-default mode 0o{:o} is not supported", mode); + // currently we only support that the owner must always have + // read-write permissions and that none of the owner, group + // and other may have execute permissions. + let owner_has_read_write_permissions = mode & 0o600 == 0o600; + let has_any_execute_permissions = mode & 0o111 != 0; + if !owner_has_read_write_permissions || has_any_execute_permissions { + throw_unsup_format!("mode 0o{:o} is not supported", mode); } mirror |= o_creat; diff --git a/test_dependencies/Cargo.lock b/test_dependencies/Cargo.lock index c728e7c077..46d198e806 100644 --- a/test_dependencies/Cargo.lock +++ b/test_dependencies/Cargo.lock @@ -26,6 +26,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -57,6 +66,15 @@ dependencies = [ "libc", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "libc" version = "0.2.137" @@ -110,6 +128,7 @@ dependencies = [ "num_cpus", "page_size", "rand", + "tempfile", "tokio", ] @@ -225,6 +244,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -267,6 +295,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "tokio" version = "1.22.0" diff --git a/test_dependencies/Cargo.toml b/test_dependencies/Cargo.toml index 3a80e8c964..052ab7fd44 100644 --- a/test_dependencies/Cargo.toml +++ b/test_dependencies/Cargo.toml @@ -13,6 +13,7 @@ tokio = { version = "1.0", features = ["full"] } libc = "0.2" page_size = "0.5" num_cpus = "1.10.1" +tempfile = "3" getrandom_1 = { package = "getrandom", version = "0.1" } getrandom = { version = "0.2" } diff --git a/tests/pass-dep/tempfile.rs b/tests/pass-dep/tempfile.rs new file mode 100644 index 0000000000..681dc6d015 --- /dev/null +++ b/tests/pass-dep/tempfile.rs @@ -0,0 +1,39 @@ +//@ignore-target-windows: no libc on Windows +//@compile-flags: -Zmiri-disable-isolation + +use std::ffi::{CStr, CString}; +use std::path::PathBuf; + +/// Test that the [`tempfile`] crate is compatible with miri. +fn main() { + // test_tempfile(); // does not work when host!=target + test_tempfile_in(); +} + +fn tmp() -> 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); + + 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) + } +} + +// does not work when host!=target: +// fn test_tempfile() { +// tempfile::tempfile().unwrap(); +// } + +fn test_tempfile_in() { + let dir_path = tmp(); + tempfile::tempfile_in(dir_path).unwrap(); +}