Skip to content

Commit 7fafbde

Browse files
committed
Auto merge of #2275 - RalfJung:permissive-provenance-for-all, r=RalfJung
Enable permissive provenance by default This completes the plan laid out in #2133: - We use permissive provenance with wildcard pointers by default. - We print a warning on int2ptr casts. `-Zmiri-permissive-provenance` suppresses the warning; `-Zmiri-strict-provenance` turns it into a hard error. - Raw pointer tagging is now always enabled, so we remove the `-Zmiri-tag-raw-pointers` flag and the code for untagged pointers. (Passing the flag still works, for compatibility -- but we just ignore it, with a warning.) We also fix an intptrcast issue: - Only live allocations are considered when computing the AllocId from an address. So, finally, Miri has a good story for ptr2int2ptr roundtrips *and* no weird false negatives when doing raw pointer stuff with Stacked Borrows. :-) 🎉 Thanks a lot to everyone who helped with this, in particular `@carbotaniuman` who convinced me this is even possible. Fixes #2133 Fixes #1866 Fixes #1993
2 parents f5593de + c1eddbc commit 7fafbde

File tree

78 files changed

+440
-544
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+440
-544
lines changed

README.md

+17-30
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,11 @@ environment variable. We first document the most relevant and most commonly used
289289
`-Zmiri-disable-isolation` is set.
290290
* `-Zmiri-ignore-leaks` disables the memory leak checker, and also allows some
291291
remaining threads to exist when the main thread exits.
292+
* `-Zmiri-permissive-provenance` disables the warning for integer-to-pointer casts and
293+
[`ptr::from_exposed_addr`](https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html).
294+
This will necessarily miss some bugs as those operations are not efficiently and accurately
295+
implementable in a sanitizer, but it will only miss bugs that concern memory/pointers which is
296+
subject to these operations.
292297
* `-Zmiri-preemption-rate` configures the probability that at the end of a basic block, the active
293298
thread will be preempted. The default is `0.01` (i.e., 1%). Setting this to `0` disables
294299
preemption.
@@ -306,7 +311,17 @@ environment variable. We first document the most relevant and most commonly used
306311
* `-Zmiri-strict-provenance` enables [strict
307312
provenance](https://github.com/rust-lang/rust/issues/95228) checking in Miri. This means that
308313
casting an integer to a pointer yields a result with 'invalid' provenance, i.e., with provenance
309-
that cannot be used for any memory access. Also implies `-Zmiri-tag-raw-pointers`.
314+
that cannot be used for any memory access.
315+
* `-Zmiri-symbolic-alignment-check` makes the alignment check more strict. By default, alignment is
316+
checked by casting the pointer to an integer, and making sure that is a multiple of the alignment.
317+
This can lead to cases where a program passes the alignment check by pure chance, because things
318+
"happened to be" sufficiently aligned -- there is no UB in this execution but there would be UB in
319+
others. To avoid such cases, the symbolic alignment check only takes into account the requested
320+
alignment of the relevant allocation, and the offset into that allocation. This avoids missing
321+
such bugs, but it also incurs some false positives when the code does manual integer arithmetic to
322+
ensure alignment. (The standard library `align_to` method works fine in both modes; under
323+
symbolic alignment it only fills the middle slice when the allocation guarantees sufficient
324+
alignment.)
310325

311326
The remaining flags are for advanced use only, and more likely to change or be removed.
312327
Some of these are **unsound**, which means they can lead
@@ -321,7 +336,7 @@ to Miri failing to detect cases of undefined behavior in a program.
321336
integers via `mem::transmute` or union/pointer type punning. This has two effects: it disables the
322337
check against integers storing a pointer (i.e., data with provenance), thus allowing
323338
pointer-to-integer transmutation, and it treats integer-to-pointer transmutation as equivalent to
324-
a cast. Using this flag is **unsound** and
339+
a cast. Implies `-Zmiri-permissive-provenance`. Using this flag is **unsound** and
325340
[deprecated](https://github.com/rust-lang/miri/issues/2188).
326341
* `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag
327342
is **unsound**.
@@ -354,27 +369,6 @@ to Miri failing to detect cases of undefined behavior in a program.
354369
application instead of raising an error within the context of Miri (and halting
355370
execution). Note that code might not expect these operations to ever panic, so
356371
this flag can lead to strange (mis)behavior.
357-
* `-Zmiri-permissive-provenance` is **experimental**. This will make Miri do a
358-
best-effort attempt to implement the semantics of
359-
[`expose_addr`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.expose_addr)
360-
and
361-
[`ptr::from_exposed_addr`](https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html)
362-
for pointer-to-int and int-to-pointer casts, respectively. This will
363-
necessarily miss some bugs as those semantics are not efficiently
364-
implementable in a sanitizer, but it will only miss bugs that concerns
365-
memory/pointers which is subject to these operations.
366-
* `-Zmiri-symbolic-alignment-check` makes the alignment check more strict. By
367-
default, alignment is checked by casting the pointer to an integer, and making
368-
sure that is a multiple of the alignment. This can lead to cases where a
369-
program passes the alignment check by pure chance, because things "happened to
370-
be" sufficiently aligned -- there is no UB in this execution but there would
371-
be UB in others. To avoid such cases, the symbolic alignment check only takes
372-
into account the requested alignment of the relevant allocation, and the
373-
offset into that allocation. This avoids missing such bugs, but it also
374-
incurs some false positives when the code does manual integer arithmetic to
375-
ensure alignment. (The standard library `align_to` method works fine in both
376-
modes; under symbolic alignment it only fills the middle slice when the
377-
allocation guarantees sufficient alignment.)
378372
* `-Zmiri-track-alloc-id=<id1>,<id2>,...` shows a backtrace when the given allocations are
379373
being allocated or freed. This helps in debugging memory leaks and
380374
use after free bugs. Specifying this argument multiple times does not overwrite the previous
@@ -389,13 +383,6 @@ to Miri failing to detect cases of undefined behavior in a program.
389383
happening and where in your code would be a good place to look for it.
390384
Specifying this argument multiple times does not overwrite the previous
391385
values, instead it appends its values to the list. Listing a tag multiple times has no effect.
392-
* `-Zmiri-tag-raw-pointers` makes Stacked Borrows assign proper tags even for raw pointers. This can
393-
make valid code using int-to-ptr casts fail to pass the checks, but also can help identify latent
394-
aliasing issues in code that Miri accepts by default. You can recognize false positives by
395-
`<untagged>` occurring in the message -- this indicates a pointer that was cast from an integer,
396-
so Miri was unable to track this pointer. Note that it is not currently guaranteed that code that
397-
works with `-Zmiri-tag-raw-pointers` also works without `-Zmiri-tag-raw-pointers`, but for the
398-
vast majority of code, this will be the case.
399386

400387
[function ABI]: https://doc.rust-lang.org/reference/items/functions.html#extern-function-qualifier
401388

src/bin/miri.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ fn main() {
340340
Please let us know at <https://github.com/rust-lang/miri/issues/2188> if you rely on this flag."
341341
);
342342
miri_config.allow_ptr_int_transmute = true;
343+
miri_config.provenance_mode = ProvenanceMode::Permissive;
343344
} else if arg == "-Zmiri-disable-abi-check" {
344345
miri_config.check_abi = false;
345346
} else if arg == "-Zmiri-disable-isolation" {
@@ -374,20 +375,18 @@ fn main() {
374375
} else if arg == "-Zmiri-panic-on-unsupported" {
375376
miri_config.panic_on_unsupported = true;
376377
} else if arg == "-Zmiri-tag-raw-pointers" {
377-
miri_config.tag_raw = true;
378+
eprintln!("WARNING: `-Zmiri-tag-raw-pointers` has no effect; it is enabled by default");
378379
} else if arg == "-Zmiri-strict-provenance" {
379380
miri_config.provenance_mode = ProvenanceMode::Strict;
380-
miri_config.tag_raw = true;
381+
miri_config.allow_ptr_int_transmute = false;
381382
} else if arg == "-Zmiri-permissive-provenance" {
382383
miri_config.provenance_mode = ProvenanceMode::Permissive;
383-
miri_config.tag_raw = true;
384384
} else if arg == "-Zmiri-mute-stdout-stderr" {
385385
miri_config.mute_stdout_stderr = true;
386386
} else if arg == "-Zmiri-track-raw-pointers" {
387387
eprintln!(
388-
"WARNING: -Zmiri-track-raw-pointers has been renamed to -Zmiri-tag-raw-pointers, the old name is deprecated."
388+
"WARNING: `-Zmiri-track-raw-pointers` has no effect; it is enabled by default"
389389
);
390-
miri_config.tag_raw = true;
391390
} else if let Some(param) = arg.strip_prefix("-Zmiri-seed=") {
392391
if miri_config.seed.is_some() {
393392
panic!("Cannot specify -Zmiri-seed multiple times!");
@@ -410,7 +409,7 @@ fn main() {
410409
err
411410
),
412411
};
413-
for id in ids.into_iter().map(miri::PtrId::new) {
412+
for id in ids.into_iter().map(miri::SbTag::new) {
414413
if let Some(id) = id {
415414
miri_config.tracked_pointer_tags.insert(id);
416415
} else {

src/diagnostics.rs

+25-20
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ pub enum NonHaltingDiagnostic {
6969
FreedAlloc(AllocId),
7070
RejectedIsolatedOp(String),
7171
ProgressReport,
72+
Int2Ptr {
73+
details: bool,
74+
},
7275
}
7376

7477
/// Level of Miri specific diagnostics
@@ -177,24 +180,6 @@ pub fn report_error<'tcx, 'mir>(
177180
helps.push((Some(*protection_span), "this protector is live for this call".to_string()));
178181
}
179182
}
180-
Some(TagHistory::Untagged{ recently_created, recently_invalidated, matching_created, protected }) => {
181-
if let Some((range, span)) = recently_created {
182-
let msg = format!("tag was most recently created at offsets {}", HexRange(*range));
183-
helps.push((Some(*span), msg));
184-
}
185-
if let Some((range, span)) = recently_invalidated {
186-
let msg = format!("tag was later invalidated at offsets {}", HexRange(*range));
187-
helps.push((Some(*span), msg));
188-
}
189-
if let Some((range, span)) = matching_created {
190-
let msg = format!("this tag was also created here at offsets {}", HexRange(*range));
191-
helps.push((Some(*span), msg));
192-
}
193-
if let Some((protecting_tag, protecting_tag_span, protection_span)) = protected {
194-
helps.push((Some(*protecting_tag_span), format!("{:?} was protected due to a tag which was created here", protecting_tag)));
195-
helps.push((Some(*protection_span), "this protector is live for this call".to_string()));
196-
}
197-
}
198183
None => {}
199184
}
200185
helps
@@ -468,15 +453,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
468453
format!("{op} was made to return an error due to isolation"),
469454
ProgressReport =>
470455
format!("progress report: current operation being executed is here"),
456+
Int2Ptr { .. } => format!("integer-to-pointer cast"),
471457
};
472458

473459
let (title, diag_level) = match e {
474460
RejectedIsolatedOp(_) =>
475461
("operation rejected by isolation", DiagLevel::Warning),
476-
_ => ("tracking was triggered", DiagLevel::Note),
462+
Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning),
463+
CreatedPointerTag(..)
464+
| PoppedPointerTag(..)
465+
| CreatedCallId(..)
466+
| CreatedAlloc(..)
467+
| FreedAlloc(..)
468+
| ProgressReport => ("tracking was triggered", DiagLevel::Note),
469+
};
470+
471+
let helps = match e {
472+
Int2Ptr { details: true } =>
473+
vec![
474+
(None, format!("this program is using integer-to-pointer casts or (equivalently) `from_exposed_addr`,")),
475+
(None, format!("which means that Miri might miss pointer bugs in this program")),
476+
(None, format!("see https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation")),
477+
(None, format!("to ensure that Miri does not miss bugs in your program, use `with_addr` (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance) instead")),
478+
(None, format!("you can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics")),
479+
(None, format!("alternatively, the `-Zmiri-permissive-provenance` flag disables this warning")),
480+
],
481+
_ => vec![],
477482
};
478483

479-
report_msg(this, diag_level, title, vec![msg], vec![], &stacktrace);
484+
report_msg(this, diag_level, title, vec![msg], helps, &stacktrace);
480485
}
481486
});
482487
}

src/eval.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,11 @@ pub struct MiriConfig {
9696
/// The seed to use when non-determinism or randomness are required (e.g. ptr-to-int cast, `getrandom()`).
9797
pub seed: Option<u64>,
9898
/// The stacked borrows pointer ids to report about
99-
pub tracked_pointer_tags: HashSet<PtrId>,
99+
pub tracked_pointer_tags: HashSet<SbTag>,
100100
/// The stacked borrows call IDs to report about
101101
pub tracked_call_ids: HashSet<CallId>,
102102
/// The allocation ids to report about.
103103
pub tracked_alloc_ids: HashSet<AllocId>,
104-
/// Whether to track raw pointers in stacked borrows.
105-
pub tag_raw: bool,
106104
/// Determine if data race detection should be enabled
107105
pub data_race_detector: bool,
108106
/// Determine if weak memory emulation should be enabled. Requires data race detection to be enabled
@@ -146,14 +144,13 @@ impl Default for MiriConfig {
146144
tracked_pointer_tags: HashSet::default(),
147145
tracked_call_ids: HashSet::default(),
148146
tracked_alloc_ids: HashSet::default(),
149-
tag_raw: false,
150147
data_race_detector: true,
151148
weak_memory_emulation: true,
152149
cmpxchg_weak_failure_rate: 0.8, // 80%
153150
measureme_out: None,
154151
panic_on_unsupported: false,
155152
backtrace_style: BacktraceStyle::Short,
156-
provenance_mode: ProvenanceMode::Legacy,
153+
provenance_mode: ProvenanceMode::Default,
157154
mute_stdout_stderr: false,
158155
preemption_rate: 0.01, // 1%
159156
report_progress: None,

0 commit comments

Comments
 (0)