Skip to content

Commit 4a34a6c

Browse files
committed
miri isolation configuration using two flags
Instead of using a single flag for both to disable isolation and to configure error behaviour, use a dedicated flag for each. For the former, continue using `-Zmiri-disable-isolation`. For the latter, replaced `-Zmiri-isolated-op` with `-Zmiri-isolation-error` flag to control the error behaviour of miri when op is run in isolation.
1 parent 7e0dd26 commit 4a34a6c

File tree

8 files changed

+69
-42
lines changed

8 files changed

+69
-42
lines changed

src/bin/miri.rs

+33-13
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ fn main() {
203203
let mut miri_config = miri::MiriConfig::default();
204204
let mut rustc_args = vec![];
205205
let mut after_dashdash = false;
206+
207+
// If user has explicitly enabled isolation
208+
let mut isolation_enabled: Option<bool> = None;
206209
for arg in env::args() {
207210
if rustc_args.is_empty() {
208211
// Very first arg: binary name.
@@ -228,8 +231,38 @@ fn main() {
228231
miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
229232
}
230233
"-Zmiri-disable-isolation" => {
234+
if let Some(true) = isolation_enabled {
235+
panic!(
236+
"-Zmiri-disable-isolation cannot be used along with -Zmiri-isolation-error"
237+
);
238+
} else {
239+
isolation_enabled = Some(false);
240+
}
231241
miri_config.isolated_op = miri::IsolatedOp::Allow;
232242
}
243+
arg if arg.starts_with("-Zmiri-isolation-error=") => {
244+
if let Some(false) = isolation_enabled {
245+
panic!(
246+
"-Zmiri-isolation-error cannot be used along with -Zmiri-disable-isolation"
247+
);
248+
} else {
249+
isolation_enabled = Some(true);
250+
}
251+
252+
miri_config.isolated_op = match arg
253+
.strip_prefix("-Zmiri-isolation-error=")
254+
.unwrap()
255+
{
256+
"abort" => miri::IsolatedOp::Reject(miri::RejectOpWith::Abort),
257+
"ignore" => miri::IsolatedOp::Reject(miri::RejectOpWith::NoWarning),
258+
"warn" => miri::IsolatedOp::Reject(miri::RejectOpWith::Warning),
259+
"warn-nobacktrace" =>
260+
miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace),
261+
_ => panic!(
262+
"-Zmiri-isolation-error must be `abort`, `ignore`, `warn`, or `warn-nobacktrace`"
263+
),
264+
};
265+
}
233266
"-Zmiri-ignore-leaks" => {
234267
miri_config.ignore_leaks = true;
235268
}
@@ -322,19 +355,6 @@ fn main() {
322355
let measureme_out = arg.strip_prefix("-Zmiri-measureme=").unwrap();
323356
miri_config.measureme_out = Some(measureme_out.to_string());
324357
}
325-
arg if arg.starts_with("-Zmiri-isolated-op=") => {
326-
let action = match arg.strip_prefix("-Zmiri-isolated-op=").unwrap() {
327-
"hide" => miri::IsolatedOp::Reject(miri::RejectOpWith::NoWarning),
328-
"warn" => miri::IsolatedOp::Reject(miri::RejectOpWith::Warning),
329-
"warn-nobacktrace" =>
330-
miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace),
331-
"allow" => miri::IsolatedOp::Allow,
332-
_ => panic!(
333-
"-Zmiri-isolated-op must be `hide`, `warn`, `warn-nobacktrace`, or `allow`"
334-
),
335-
};
336-
miri_config.isolated_op = action;
337-
}
338358
_ => {
339359
// Forward to rustc.
340360
rustc_args.push(arg);

src/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub fn report_error<'tcx, 'mir>(
7171
#[rustfmt::skip]
7272
let helps = match info {
7373
UnsupportedInIsolation(_) =>
74-
vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
74+
vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation; or pass `-Zmiri-isolation-error=warn to configure miri to warn about isolation and continue instead of aborting")],
7575
ExperimentalUb { url, .. } =>
7676
vec![
7777
format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),

src/eval.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,27 @@ pub enum AlignmentCheck {
2424

2525
#[derive(Copy, Clone, Debug, PartialEq)]
2626
pub enum RejectOpWith {
27-
/// Do not print warning about rejected isolated op
27+
/// Isolated op is rejected with an abort of the machine.
28+
Abort,
29+
30+
/// If not Abort, miri returns an error for an isolated op.
31+
/// Following options determine if user should be warned about such error.
32+
/// Do not print warning about rejected isolated op.
2833
NoWarning,
2934

30-
/// Print a warning about rejected isolated op, with backtrace
35+
/// Print a warning about rejected isolated op, with backtrace.
3136
Warning,
3237

33-
/// Print a warning about rejected isolated op, without backtrace
38+
/// Print a warning about rejected isolated op, without backtrace.
3439
WarningWithoutBacktrace,
3540
}
3641

3742
#[derive(Copy, Clone, Debug, PartialEq)]
3843
pub enum IsolatedOp {
39-
/// Reject op requiring communication with the host. Usually, miri
40-
/// returns an error code for such op, and prints a warning
41-
/// about it. Warning levels are controlled by `RejectOpWith` enum.
44+
/// Reject an op requiring communication with the host. By
45+
/// default, miri rejects the op with an abort. If not, it returns
46+
/// an error code, and prints a warning about it. Warning levels
47+
/// are controlled by `RejectOpWith` enum.
4248
Reject(RejectOpWith),
4349

4450
/// Execute op requiring communication with the host, i.e. disable isolation.
@@ -88,7 +94,7 @@ impl Default for MiriConfig {
8894
validate: true,
8995
stacked_borrows: true,
9096
check_alignment: AlignmentCheck::Int,
91-
isolated_op: IsolatedOp::Reject(RejectOpWith::WarningWithoutBacktrace),
97+
isolated_op: IsolatedOp::Reject(RejectOpWith::Abort),
9298
ignore_leaks: false,
9399
excluded_env_vars: vec![],
94100
args: vec![],

src/helpers.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -392,28 +392,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
392392
/// case.
393393
fn check_no_isolation(&self, name: &str) -> InterpResult<'tcx> {
394394
if !self.eval_context_ref().machine.communicate() {
395-
isolation_error(name)?;
395+
self.reject_in_isolation(name, RejectOpWith::Abort)?;
396396
}
397397
Ok(())
398398
}
399399

400400
/// Helper function used inside the shims of foreign functions which reject the op
401401
/// when isolation is enabled. It is used to print a warning/backtrace about the rejection.
402-
fn report_rejected_op(&self, op_name: &str, reject_with: RejectOpWith) {
402+
fn reject_in_isolation(&self, op_name: &str, reject_with: RejectOpWith) -> InterpResult<'tcx> {
403403
let this = self.eval_context_ref();
404404
match reject_with {
405+
RejectOpWith::Abort => isolation_abort_error(op_name),
405406
RejectOpWith::WarningWithoutBacktrace => {
406407
let msg = format!("`{}` was made to return an error due to isolation", op_name);
407408
let mut warn = this.tcx.sess.struct_warn(&msg);
408-
warn.note("run with -Zmiri-isolated-op=warn to get warning with a backtrace");
409-
warn.note("run with -Zmiri-isolated-op=hide to hide warning");
410-
warn.note("run with -Zmiri-isolated-op=allow to disable isolation");
409+
warn.note("run with -Zmiri-isolation-error=warn to get warning with a backtrace");
410+
warn.note("run with -Zmiri-isolation-error=ignore to hide warning");
411+
warn.note("run with -Zmiri-disable-isolation to disable isolation");
411412
warn.emit();
413+
Ok(())
412414
}
413415
RejectOpWith::Warning => {
414416
register_diagnostic(NonHaltingDiagnostic::RejectedIsolatedOp(op_name.to_string()));
417+
Ok(())
415418
}
416-
RejectOpWith::NoWarning => {} // no warning
419+
RejectOpWith::NoWarning => Ok(()), // no warning
417420
}
418421
}
419422

@@ -664,10 +667,7 @@ pub fn check_abi<'a>(abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> {
664667
}
665668
}
666669

667-
pub fn isolation_error(name: &str) -> InterpResult<'static> {
668-
// FIXME: This function has been deprecated. It's only used for
669-
// the ops which are not converted to return a proper error code
670-
// in isolation.
670+
pub fn isolation_abort_error(name: &str) -> InterpResult<'static> {
671671
throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!(
672672
"{} not available when isolation is enabled",
673673
name,

src/shims/env.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
323323
);
324324

325325
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
326+
this.reject_in_isolation("getcwd", reject_with)?;
326327
let err = Error::new(ErrorKind::NotFound, "rejected due to isolation");
327328
this.set_last_error_from_io_error(err)?;
328-
this.report_rejected_op("getcwd", reject_with);
329329
} else {
330330
let buf = this.read_scalar(&buf_op)?.check_init()?;
331331
let size = this.read_scalar(&size_op)?.to_machine_usize(&*this.tcx)?;
@@ -355,9 +355,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
355355
this.assert_target_os("windows", "GetCurrentDirectoryW");
356356

357357
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
358+
this.reject_in_isolation("GetCurrentDirectoryW", reject_with)?;
358359
let err = Error::new(ErrorKind::NotFound, "rejected due to isolation");
359360
this.set_last_error_from_io_error(err)?;
360-
this.report_rejected_op("GetCurrentDirectoryW", reject_with);
361361
} else {
362362
let size = u64::from(this.read_scalar(size_op)?.to_u32()?);
363363
let buf = this.read_scalar(buf_op)?.check_init()?;
@@ -383,9 +383,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
383383
);
384384

385385
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
386+
this.reject_in_isolation("chdir", reject_with)?;
386387
let err = Error::new(ErrorKind::NotFound, "rejected due to isolation");
387388
this.set_last_error_from_io_error(err)?;
388-
this.report_rejected_op("chdir", reject_with);
389389

390390
Ok(-1)
391391
} else {
@@ -412,9 +412,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
412412
this.assert_target_os("windows", "SetCurrentDirectoryW");
413413

414414
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
415+
this.reject_in_isolation("SetCurrentDirectoryW", reject_with)?;
415416
let err = Error::new(ErrorKind::NotFound, "rejected due to isolation");
416417
this.set_last_error_from_io_error(err)?;
417-
this.report_rejected_op("SetCurrentDirectoryW", reject_with);
418418

419419
Ok(0)
420420
} else {

src/shims/posix/fs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl FileDescriptor for io::Stdin {
127127
) -> InterpResult<'tcx, io::Result<usize>> {
128128
if !communicate_allowed {
129129
// We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
130-
helpers::isolation_error("`read` from stdin")?;
130+
helpers::isolation_abort_error("`read` from stdin")?;
131131
}
132132
Ok(Read::read(self, bytes))
133133
}

tests/run-pass/current_dir_with_isolation.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// compile-flags: -Zmiri-isolation-error=warn-nobacktrace
12
use std::env;
23
use std::io::ErrorKind;
34

Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
warning: `getcwd` was made to return an error due to isolation
22
|
3-
= note: run with -Zmiri-isolated-op=warn to get warning with a backtrace
4-
= note: run with -Zmiri-isolated-op=hide to hide warning
5-
= note: run with -Zmiri-isolated-op=allow to disable isolation
3+
= note: run with -Zmiri-isolation-error=warn to get warning with a backtrace
4+
= note: run with -Zmiri-isolation-error=ignore to hide warning
5+
= note: run with -Zmiri-disable-isolation to disable isolation
66

77
warning: `chdir` was made to return an error due to isolation
88
|
9-
= note: run with -Zmiri-isolated-op=warn to get warning with a backtrace
10-
= note: run with -Zmiri-isolated-op=hide to hide warning
11-
= note: run with -Zmiri-isolated-op=allow to disable isolation
9+
= note: run with -Zmiri-isolation-error=warn to get warning with a backtrace
10+
= note: run with -Zmiri-isolation-error=ignore to hide warning
11+
= note: run with -Zmiri-disable-isolation to disable isolation
1212

0 commit comments

Comments
 (0)