diff --git a/README.md b/README.md index d3e4adfa1785..f5b8999d1c59 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,8 @@ Several `-Z` flags are relevant for Miri: * `-Zmiri-disable-isolation` disables host host isolation. As a consequence, the program has access to host resources such as environment variables and randomness (and, eventually, file systems and more). +* `-Zmiri-env-exclude=` keeps the `var` environment variable isolated from + the host. Can be used multiple times to exclude several variables. * `-Zmir-opt-level` controls how many MIR optimizations are performed. Miri overrides the default to be `0`; be advised that using any higher level can make Miri miss bugs in your program because they got optimized away. diff --git a/benches/helpers/miri_helper.rs b/benches/helpers/miri_helper.rs index 5cb938659a6c..a4f559967204 100644 --- a/benches/helpers/miri_helper.rs +++ b/benches/helpers/miri_helper.rs @@ -28,6 +28,7 @@ fn after_analysis(&mut self, compiler: &interface::Compiler) -> Compilation { let config = miri::MiriConfig { validate: true, communicate: false, + excluded_env_vars: vec![], args: vec![], seed: None, }; diff --git a/src/bin/miri-rustc-tests.rs b/src/bin/miri-rustc-tests.rs index 9ef64c38638b..3b4ad8415917 100644 --- a/src/bin/miri-rustc-tests.rs +++ b/src/bin/miri-rustc-tests.rs @@ -51,6 +51,7 @@ fn visit_item(&mut self, i: &'hir hir::Item) { let config = MiriConfig { validate: true, communicate: false, + excluded_env_vars: vec![], args: vec![], seed: None, }; @@ -69,6 +70,7 @@ fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {} let config = MiriConfig { validate: true, communicate: false, + excluded_env_vars: vec![], args: vec![], seed: None }; diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 55522a52e012..6e4bf4a6c269 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -135,6 +135,7 @@ fn main() { let mut rustc_args = vec![]; let mut miri_args = vec![]; let mut after_dashdash = false; + let mut excluded_env_vars = vec![]; for arg in std::env::args() { if rustc_args.is_empty() { // Very first arg: for `rustc`. @@ -175,6 +176,9 @@ fn main() { seed = Some(u64::from_be_bytes(bytes)); }, + arg if arg.starts_with("-Zmiri-env-exclude=") => { + excluded_env_vars.push(arg.trim_start_matches("-Zmiri-env-exclude=").to_owned()); + }, _ => { rustc_args.push(arg); } @@ -200,7 +204,13 @@ fn main() { debug!("rustc arguments: {:?}", rustc_args); debug!("miri arguments: {:?}", miri_args); - let miri_config = miri::MiriConfig { validate, communicate, args: miri_args, seed }; + let miri_config = miri::MiriConfig { + validate, + communicate, + excluded_env_vars, + seed, + args: miri_args, + }; let result = rustc_driver::report_ices_to_stderr_if_any(move || { rustc_driver::run_compiler(&rustc_args, &mut MiriCompilerCalls { miri_config }, None, None) }).and_then(|result| result); diff --git a/src/eval.rs b/src/eval.rs index bd4d8a0bef85..667491f8d477 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -22,6 +22,9 @@ pub struct MiriConfig { pub validate: bool, /// Determines if communication with the host environment is enabled. pub communicate: bool, + /// Environment variables that should always be isolated from the host. + pub excluded_env_vars: Vec, + /// Command-line arguments passed to the interpreted program. pub args: Vec, /// The seed to use when non-determinism or randomness are required (e.g. ptr-to-int cast, `getrandom()`). pub seed: Option, @@ -40,7 +43,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( MemoryExtra::new(StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.validate), ); // Complete initialization. - EnvVars::init(&mut ecx); + EnvVars::init(&mut ecx, config.excluded_env_vars); // Setup first stack-frame let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id); diff --git a/src/shims/env.rs b/src/shims/env.rs index 8f946a2b5eb1..5a5dffa1d09b 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -15,11 +15,14 @@ pub struct EnvVars { impl EnvVars { pub(crate) fn init<'mir, 'tcx>( ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>, + excluded_env_vars: Vec, ) { if ecx.machine.communicate { for (name, value) in std::env::vars() { - let var_ptr = alloc_env_var(name.as_bytes(), value.as_bytes(), ecx.memory_mut()); - ecx.machine.env_vars.map.insert(name.into_bytes(), var_ptr); + if !excluded_env_vars.contains(&name) { + let var_ptr = alloc_env_var(name.as_bytes(), value.as_bytes(), ecx.memory_mut()); + ecx.machine.env_vars.map.insert(name.into_bytes(), var_ptr); + } } } } diff --git a/tests/run-pass/env-exclude.rs b/tests/run-pass/env-exclude.rs new file mode 100644 index 000000000000..efcf7a756114 --- /dev/null +++ b/tests/run-pass/env-exclude.rs @@ -0,0 +1,6 @@ +// ignore-windows: TODO env var emulation stubbed out on Windows +// compile-flags: -Zmiri-disable-isolation -Zmiri-env-exclude=MIRI_ENV_VAR_TEST + +fn main() { + assert!(std::env::var("MIRI_ENV_VAR_TEST").is_err()); +}