Skip to content

Commit fe670d9

Browse files
committed
Consolidated settings for isolated ops
In user interface, added a new option `-Zmiri-isolated-op` which takes one of the four values -- hide, warn, warn-nobacktrace, and allow. This option can be used to both disable isolation (allow), and to control warning levels if op is rejected due to isolation. In implementation, added a new enum `IsolatedOp` to capture all the settings related to ops requiring communication with the host. Existing `communicate` flag in both miri configs and machine state will be discarded once its use is replaced with the new enum. Added a new helper function to report rejected ops in isolation according to the warning settings. Refactored miri specific diagnostics function `report_msg` to take an enum value instead of a bool, indicating the level of diagnostics. Updated shims related to current dir to use the new enum. Added a .stderr file for the new test, matching the warning thrown.
1 parent 6bd7556 commit fe670d9

File tree

8 files changed

+155
-99
lines changed

8 files changed

+155
-99
lines changed

src/bin/miri.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,14 @@ fn main() {
229229
}
230230
"-Zmiri-disable-isolation" => {
231231
miri_config.communicate = true;
232+
miri_config.isolated_op = miri::IsolatedOp::Allow;
232233
}
233234
"-Zmiri-ignore-leaks" => {
234235
miri_config.ignore_leaks = true;
235236
}
236237
"-Zmiri-track-raw-pointers" => {
237238
miri_config.track_raw = true;
238239
}
239-
"-Zmiri-track-dummy-op" => {
240-
miri_config.dummy_op_visibility = miri::DummyOpVisibility::Track;
241-
}
242-
"-Zmiri-ignore-dummy-op" => {
243-
miri_config.dummy_op_visibility = miri::DummyOpVisibility::Hide;
244-
}
245240
"--" => {
246241
after_dashdash = true;
247242
}
@@ -324,6 +319,17 @@ fn main() {
324319
};
325320
miri_config.cmpxchg_weak_failure_rate = rate;
326321
}
322+
arg if arg.starts_with("-Zmiri-isolated-op=") => {
323+
let action = match arg.strip_prefix("-Zmiri-isolated-op=").unwrap() {
324+
"hide" => miri::IsolatedOp::Reject(miri::RejectOpWith::NoWarning),
325+
"warn" => miri::IsolatedOp::Reject(miri::RejectOpWith::Warning),
326+
"warn-nobacktrace" => miri::IsolatedOp::Reject(miri::RejectOpWith::WarningWithoutBacktrace),
327+
"allow" => miri::IsolatedOp::Allow,
328+
_ => panic!("-Zmiri-isolated-op must be `hide`, `warn`, `warn-nobacktrace`, or `allow`"),
329+
330+
};
331+
miri_config.isolated_op = action;
332+
}
327333
_ => {
328334
// Forward to rustc.
329335
rustc_args.push(arg);

src/diagnostics.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,14 @@ pub enum NonHaltingDiagnostic {
4040
CreatedCallId(CallId),
4141
CreatedAlloc(AllocId),
4242
FreedAlloc(AllocId),
43-
DummyOpInIsolation(String),
43+
RejectedIsolatedOp(String),
44+
}
45+
46+
/// Level of Miri specific diagnostics
47+
enum DiagLevel {
48+
Error,
49+
Warning,
50+
Note,
4451
}
4552

4653
/// Emit a custom diagnostic without going through the miri-engine machinery
@@ -118,7 +125,7 @@ pub fn report_error<'tcx, 'mir>(
118125
let msg = e.to_string();
119126
report_msg(
120127
*ecx.tcx,
121-
/*error*/ true,
128+
DiagLevel::Error,
122129
&format!("{}: {}", title, msg),
123130
msg,
124131
helps,
@@ -155,18 +162,19 @@ pub fn report_error<'tcx, 'mir>(
155162
/// Also emits a full stacktrace of the interpreter stack.
156163
fn report_msg<'tcx>(
157164
tcx: TyCtxt<'tcx>,
158-
error: bool,
165+
diag_level: DiagLevel,
159166
title: &str,
160167
span_msg: String,
161168
mut helps: Vec<String>,
162169
stacktrace: &[FrameInfo<'tcx>],
163170
) {
164171
let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span);
165-
let mut err = if error {
166-
tcx.sess.struct_span_err(span, title)
167-
} else {
168-
tcx.sess.diagnostic().span_note_diag(span, title)
172+
let mut err = match diag_level {
173+
DiagLevel::Error => tcx.sess.struct_span_err(span, title),
174+
DiagLevel::Warning => tcx.sess.struct_span_warn(span, title),
175+
DiagLevel::Note => tcx.sess.diagnostic().span_note_diag(span, title),
169176
};
177+
170178
// Show main message.
171179
if span != DUMMY_SP {
172180
err.span_label(span, span_msg);
@@ -280,12 +288,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
280288
CreatedCallId(id) => format!("function call with id {}", id),
281289
CreatedAlloc(AllocId(id)) => format!("created allocation with id {}", id),
282290
FreedAlloc(AllocId(id)) => format!("freed allocation with id {}", id),
283-
DummyOpInIsolation(op) => format!("produced dummy error for `{}`", op),
291+
RejectedIsolatedOp(ref op) => format!("`{}` was made to return an error due to isolation", op),
284292
};
293+
294+
let (title, diag_level) = match e {
295+
RejectedIsolatedOp(_) => ("operation rejected by isolation", DiagLevel::Warning),
296+
_ => ("tracking was triggered", DiagLevel::Note),
297+
};
298+
285299
report_msg(
286300
*this.tcx,
287-
/*error*/ false,
288-
"tracking was triggered",
301+
diag_level,
302+
title,
289303
msg,
290304
vec![],
291305
&stacktrace,

src/eval.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,26 @@ pub enum AlignmentCheck {
2323
}
2424

2525
#[derive(Copy, Clone, Debug)]
26-
pub enum DummyOpVisibility {
27-
/// Do not report a dummy op
28-
Hide,
29-
/// Print a warning without a backtrace, once per dummy op
30-
Warn,
31-
/// Print a note with a backtrace, once per line calling dummy op
32-
Track,
26+
pub enum RejectOpWith {
27+
/// Do not print warning about rejected isolated op
28+
NoWarning,
29+
30+
/// Print a warning about rejected isolated op, with backtrace
31+
Warning,
32+
33+
/// Print a warning about rejected isolated op, without backtrace
34+
WarningWithoutBacktrace,
35+
}
36+
37+
#[derive(Copy, Clone, Debug)]
38+
pub enum IsolatedOp {
39+
/// Reject op requiring communication with the host. Usually, miri
40+
/// generates a fake error for such op, and prints a warning
41+
/// about it. Warning levels are controlled by `RejectOpWith` enum.
42+
Reject(RejectOpWith),
43+
44+
/// Execute op requiring communication with the host, i.e. disable isolation.
45+
Allow,
3346
}
3447

3548
/// Configuration needed to spawn a Miri instance.
@@ -43,6 +56,8 @@ pub struct MiriConfig {
4356
pub check_alignment: AlignmentCheck,
4457
/// Determines if communication with the host environment is enabled.
4558
pub communicate: bool,
59+
/// Action for an op requiring communication with the host.
60+
pub isolated_op: IsolatedOp,
4661
/// Determines if memory leaks should be ignored.
4762
pub ignore_leaks: bool,
4863
/// Environment variables that should always be isolated from the host.
@@ -64,8 +79,6 @@ pub struct MiriConfig {
6479
/// Rate of spurious failures for compare_exchange_weak atomic operations,
6580
/// between 0.0 and 1.0, defaulting to 0.8 (80% chance of failure).
6681
pub cmpxchg_weak_failure_rate: f64,
67-
/// Visibility level of a dummy op performed in isolation mode
68-
pub dummy_op_visibility: DummyOpVisibility,
6982
}
7083

7184
impl Default for MiriConfig {
@@ -75,6 +88,7 @@ impl Default for MiriConfig {
7588
stacked_borrows: true,
7689
check_alignment: AlignmentCheck::Int,
7790
communicate: false,
91+
isolated_op: IsolatedOp::Reject(RejectOpWith::WarningWithoutBacktrace),
7892
ignore_leaks: false,
7993
excluded_env_vars: vec![],
8094
args: vec![],
@@ -85,7 +99,6 @@ impl Default for MiriConfig {
8599
track_raw: false,
86100
data_race_detector: true,
87101
cmpxchg_weak_failure_rate: 0.8,
88-
dummy_op_visibility: DummyOpVisibility::Warn,
89102
}
90103
}
91104
}

src/helpers.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -397,23 +397,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
397397
Ok(())
398398
}
399399

400-
/// Helper function used inside the shims of foreign functions which produce a dummy error
401-
/// when isolation is enabled. It is used to print a warning/backtrace, informing this
402-
/// decision to the user.
403-
fn report_dummy_in_isolation(&self, name: &str) {
400+
/// Helper function used inside the shims of foreign functions which reject the op
401+
/// 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) {
404403
let this = self.eval_context_ref();
405-
match this.machine.dummy_op_visibility {
406-
DummyOpVisibility::Warn => {
407-
let msg = format!("`{}` in isolation mode produced a dummy error", name);
404+
match reject_with {
405+
RejectOpWith::WarningWithoutBacktrace => {
406+
let msg = format!("`{}` was made to return an error due to isolation", op_name);
408407
let mut warn = this.tcx.sess.struct_warn(&msg);
409-
warn.note("run with -Zmiri-track-dummy-op to track with a backtrace");
410-
warn.note("run with -Zmiri-ignore-dummy-op to ignore warning");
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");
411411
warn.emit();
412412
}
413-
DummyOpVisibility::Track => {
414-
register_diagnostic(NonHaltingDiagnostic::DummyOpInIsolation(name.to_string()));
413+
RejectOpWith::Warning => {
414+
register_diagnostic(NonHaltingDiagnostic::RejectedIsolatedOp(op_name.to_string()));
415415
}
416-
DummyOpVisibility::Hide => {} // no diagnostics
416+
RejectOpWith::NoWarning => {} // no warning
417417
}
418418
}
419419

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub use crate::diagnostics::{
5757
register_diagnostic, report_error, EvalContextExt as DiagnosticsEvalContextExt,
5858
NonHaltingDiagnostic, TerminationInfo,
5959
};
60-
pub use crate::eval::{create_ecx, eval_main, AlignmentCheck, DummyOpVisibility, MiriConfig};
60+
pub use crate::eval::{create_ecx, eval_main, AlignmentCheck, IsolatedOp, MiriConfig, RejectOpWith};
6161
pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
6262
pub use crate::machine::{
6363
AllocExtra, Evaluator, FrameData, MemoryExtra, MiriEvalContext, MiriEvalContextExt,

src/machine.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,10 @@ pub struct Evaluator<'mir, 'tcx> {
253253
/// and random number generation is delegated to the host.
254254
pub(crate) communicate: bool,
255255

256-
/// Level of user visibility to dummy ops run in isolation mode.
257-
pub(crate) dummy_op_visibility: DummyOpVisibility,
256+
/// What should Miri do when an op requires communicating with the host,
257+
/// such as accessing host env vars, random number generation, and
258+
/// file system access.
259+
pub(crate) isolated_op: IsolatedOp,
258260

259261
/// Whether to enforce the validity invariant.
260262
pub(crate) validate: bool,
@@ -291,7 +293,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
291293
cmd_line: None,
292294
tls: TlsData::default(),
293295
communicate: config.communicate,
294-
dummy_op_visibility: config.dummy_op_visibility,
296+
isolated_op: config.isolated_op,
295297
validate: config.validate,
296298
file_handler: Default::default(),
297299
dir_handler: Default::default(),

0 commit comments

Comments
 (0)