From 0eed5e64de4c7497785f5df7f2cf376d1e6afb91 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Tue, 24 Sep 2019 14:42:38 -0500 Subject: [PATCH 1/2] Add `chdir` shim --- src/shims/env.rs | 26 ++++++++++++++++++++++++++ src/shims/foreign_items.rs | 5 +++++ tests/run-pass/change_current_dir.rs | 14 ++++++++++++++ tests/run-pass/get_current_dir.rs | 6 ------ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 tests/run-pass/change_current_dir.rs delete mode 100644 tests/run-pass/get_current_dir.rs diff --git a/src/shims/env.rs b/src/shims/env.rs index e2a9452045..074baa51f8 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::env; +use std::path::Path; use crate::stacked_borrows::Tag; use crate::*; @@ -151,4 +152,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } Ok(Scalar::ptr_null(&*this.tcx)) } + + fn chdir(&mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> { + let this = self.eval_context_mut(); + + if !this.machine.communicate { + throw_unsup_format!("`chdir` not available when isolation is enabled") + } + + let path_bytes = this + .memory() + .read_c_str(this.read_scalar(path_op)?.not_undef()?)?; + + let path = Path::new( + std::str::from_utf8(path_bytes) + .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?, + ); + + match env::set_current_dir(path) { + Ok(()) => Ok(0), + Err(e) => { + this.machine.last_error = e.raw_os_error().unwrap() as u32; + Ok(-1) + } + } + } } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 45f167bea5..fedb6354b8 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -441,6 +441,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(result, dest)?; } + "chdir" => { + let result = this.chdir(args[0])?; + this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?; + } + "write" => { let fd = this.read_scalar(args[0])?.to_i32()?; let buf = this.read_scalar(args[1])?.not_undef()?; diff --git a/tests/run-pass/change_current_dir.rs b/tests/run-pass/change_current_dir.rs new file mode 100644 index 0000000000..fa8220339d --- /dev/null +++ b/tests/run-pass/change_current_dir.rs @@ -0,0 +1,14 @@ +// ignore-windows: TODO the windows hook is not done yet +// compile-flags: -Zmiri-disable-isolation +use std::env; +use std::path::Path; + +fn main() { + // test that `getcwd` is available + let cwd = env::current_dir().unwrap(); + let parent = cwd.parent().unwrap_or(&cwd); + // test that `chdir` is available + assert!(env::set_current_dir(&Path::new("..")).is_ok()); + // test that `..` goes to the parent directory + assert_eq!(env::current_dir().unwrap(), parent); +} diff --git a/tests/run-pass/get_current_dir.rs b/tests/run-pass/get_current_dir.rs deleted file mode 100644 index 45efd06d3f..0000000000 --- a/tests/run-pass/get_current_dir.rs +++ /dev/null @@ -1,6 +0,0 @@ -// ignore-windows: TODO the windows hook is not done yet -// compile-flags: -Zmiri-disable-isolation - -fn main() { - std::env::current_dir().unwrap(); -} From 145a5826d5cc02b15723bb9acb6739abdac28409 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Tue, 24 Sep 2019 15:53:14 -0500 Subject: [PATCH 2/2] Check that `chdir` fails for non-utf8 paths --- tests/compile-fail/chdir_invalid_path.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/compile-fail/chdir_invalid_path.rs diff --git a/tests/compile-fail/chdir_invalid_path.rs b/tests/compile-fail/chdir_invalid_path.rs new file mode 100644 index 0000000000..22b0d723aa --- /dev/null +++ b/tests/compile-fail/chdir_invalid_path.rs @@ -0,0 +1,11 @@ +// compile-flags: -Zmiri-disable-isolation + +extern { + pub fn chdir(dir: *const u8) -> i32; +} + +fn main() { + let path = vec![0xc3u8, 0x28, 0]; + // test that `chdir` errors with invalid utf-8 path + unsafe { chdir(path.as_ptr()) }; //~ ERROR is not a valid utf-8 string +}