Skip to content

Commit 5f1a21c

Browse files
authored
Unrolled build for rust-lang#118022
Rollup merge of rust-lang#118022 - saethlin:miri, r=saethlin Miri subtree update
2 parents 2831701 + ee48a3f commit 5f1a21c

File tree

17 files changed

+252
-138
lines changed

17 files changed

+252
-138
lines changed

src/tools/miri/ci.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ case $HOST_TARGET in
108108
MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
109109
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
110110
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
111-
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthreads atomic env/var
111+
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc atomic env align
112112
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
113113
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm
114114
MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3aaa0f57b7b877ef58532a8de075d1e5a79142bf
1+
820f06b21f8373060ff7b515715b8440a6a6c197

src/tools/miri/src/borrow_tracker/mod.rs

+45-13
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl fmt::Debug for BorTag {
5959
#[derive(Debug)]
6060
pub struct FrameState {
6161
/// The ID of the call this frame corresponds to.
62-
pub call_id: CallId,
62+
call_id: CallId,
6363

6464
/// If this frame is protecting any tags, they are listed here. We use this list to do
6565
/// incremental updates of the global list of protected tags stored in the
@@ -72,7 +72,7 @@ pub struct FrameState {
7272
///
7373
/// This will contain one tag per reference passed to the function, so
7474
/// a size of 2 is enough for the vast majority of functions.
75-
pub protected_tags: SmallVec<[(AllocId, BorTag); 2]>,
75+
protected_tags: SmallVec<[(AllocId, BorTag); 2]>,
7676
}
7777

7878
impl VisitTags for FrameState {
@@ -85,29 +85,29 @@ impl VisitTags for FrameState {
8585
#[derive(Debug)]
8686
pub struct GlobalStateInner {
8787
/// Borrow tracker method currently in use.
88-
pub borrow_tracker_method: BorrowTrackerMethod,
88+
borrow_tracker_method: BorrowTrackerMethod,
8989
/// Next unused pointer ID (tag).
90-
pub next_ptr_tag: BorTag,
90+
next_ptr_tag: BorTag,
9191
/// Table storing the "base" tag for each allocation.
9292
/// The base tag is the one used for the initial pointer.
9393
/// We need this in a separate table to handle cyclic statics.
94-
pub base_ptr_tags: FxHashMap<AllocId, BorTag>,
94+
base_ptr_tags: FxHashMap<AllocId, BorTag>,
9595
/// Next unused call ID (for protectors).
96-
pub next_call_id: CallId,
96+
next_call_id: CallId,
9797
/// All currently protected tags.
9898
/// An item is protected if its tag is in this set, *and* it has the "protected" bit set.
9999
/// We add tags to this when they are created with a protector in `reborrow`, and
100100
/// we remove tags from this when the call which is protecting them returns, in
101101
/// `GlobalStateInner::end_call`. See `Stack::item_popped` for more details.
102-
pub protected_tags: FxHashMap<BorTag, ProtectorKind>,
102+
protected_tags: FxHashMap<BorTag, ProtectorKind>,
103103
/// The pointer ids to trace
104-
pub tracked_pointer_tags: FxHashSet<BorTag>,
104+
tracked_pointer_tags: FxHashSet<BorTag>,
105105
/// The call ids to trace
106-
pub tracked_call_ids: FxHashSet<CallId>,
106+
tracked_call_ids: FxHashSet<CallId>,
107107
/// Whether to recurse into datatypes when searching for pointers to retag.
108-
pub retag_fields: RetagFields,
108+
retag_fields: RetagFields,
109109
/// Whether `core::ptr::Unique` gets special (`Box`-like) handling.
110-
pub unique_is_unique: bool,
110+
unique_is_unique: bool,
111111
}
112112

113113
impl VisitTags for GlobalStateInner {
@@ -194,7 +194,7 @@ impl GlobalStateInner {
194194
}
195195

196196
/// Generates a new pointer tag. Remember to also check track_pointer_tags and log its creation!
197-
pub fn new_ptr(&mut self) -> BorTag {
197+
fn new_ptr(&mut self) -> BorTag {
198198
let id = self.next_ptr_tag;
199199
self.next_ptr_tag = id.succ().unwrap();
200200
id
@@ -210,7 +210,7 @@ impl GlobalStateInner {
210210
FrameState { call_id, protected_tags: SmallVec::new() }
211211
}
212212

213-
pub fn end_call(&mut self, frame: &machine::FrameExtra<'_>) {
213+
fn end_call(&mut self, frame: &machine::FrameExtra<'_>) {
214214
for (_, tag) in &frame
215215
.borrow_tracker
216216
.as_ref()
@@ -355,6 +355,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
355355
BorrowTrackerMethod::TreeBorrows => this.print_tree(alloc_id, show_unnamed),
356356
}
357357
}
358+
359+
fn on_stack_pop(
360+
&self,
361+
frame: &Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
362+
) -> InterpResult<'tcx> {
363+
let this = self.eval_context_ref();
364+
let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap();
365+
// The body of this loop needs `borrow_tracker` immutably
366+
// so we can't move this code inside the following `end_call`.
367+
for (alloc_id, tag) in &frame
368+
.extra
369+
.borrow_tracker
370+
.as_ref()
371+
.expect("we should have borrow tracking data")
372+
.protected_tags
373+
{
374+
// Just because the tag is protected doesn't guarantee that
375+
// the allocation still exists (weak protectors allow deallocations)
376+
// so we must check that the allocation exists.
377+
// If it does exist, then we have the guarantee that the
378+
// pointer is readable, and the implicit read access inserted
379+
// will never cause UB on the pointer itself.
380+
let (_, _, kind) = this.get_alloc_info(*alloc_id);
381+
if matches!(kind, AllocKind::LiveData) {
382+
let alloc_extra = this.get_alloc_extra(*alloc_id).unwrap();
383+
let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap();
384+
alloc_borrow_tracker.release_protector(&this.machine, borrow_tracker, *tag)?;
385+
}
386+
}
387+
borrow_tracker.borrow_mut().end_call(&frame.extra);
388+
Ok(())
389+
}
358390
}
359391

360392
/// Extra per-allocation data for borrow tracking

src/tools/miri/src/machine.rs

+2-28
Original file line numberDiff line numberDiff line change
@@ -1409,34 +1409,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
14091409
) -> InterpResult<'tcx> {
14101410
// We want this *before* the return value copy, because the return place itself is protected
14111411
// until we do `end_call` here.
1412-
if let Some(global_borrow_tracker) = &ecx.machine.borrow_tracker {
1413-
// The body of this loop needs `global_borrow_tracker` immutably
1414-
// so we can't move this code inside the following `end_call`.
1415-
for (alloc_id, tag) in &frame
1416-
.extra
1417-
.borrow_tracker
1418-
.as_ref()
1419-
.expect("we should have borrow tracking data")
1420-
.protected_tags
1421-
{
1422-
// Just because the tag is protected doesn't guarantee that
1423-
// the allocation still exists (weak protectors allow deallocations)
1424-
// so we must check that the allocation exists.
1425-
// If it does exist, then we have the guarantee that the
1426-
// pointer is readable, and the implicit read access inserted
1427-
// will never cause UB on the pointer itself.
1428-
let (_, _, kind) = ecx.get_alloc_info(*alloc_id);
1429-
if matches!(kind, AllocKind::LiveData) {
1430-
let alloc_extra = ecx.get_alloc_extra(*alloc_id).unwrap();
1431-
let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap();
1432-
alloc_borrow_tracker.release_protector(
1433-
&ecx.machine,
1434-
global_borrow_tracker,
1435-
*tag,
1436-
)?;
1437-
}
1438-
}
1439-
global_borrow_tracker.borrow_mut().end_call(&frame.extra);
1412+
if ecx.machine.borrow_tracker.is_some() {
1413+
ecx.on_stack_pop(frame)?;
14401414
}
14411415
Ok(())
14421416
}

src/tools/miri/src/shims/unix/foreign_items.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool {
2727
// `signal` is set up as a weak symbol in `init_extern_statics` (on Android) so we might as
2828
// well allow it in `dlsym`.
2929
"signal" => true,
30+
// needed at least on macOS to avoid file-based fallback in getrandom
31+
"getentropy" => true,
3032
// Give specific OSes a chance to allow their symbols.
3133
_ =>
3234
match target_os {
@@ -250,6 +252,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
250252
this.write_scalar(result, dest)?;
251253
}
252254

255+
"reallocarray" => {
256+
// Currently this function does not exist on all Unixes, e.g. on macOS.
257+
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd") {
258+
throw_unsup_format!(
259+
"`reallocarray` is not supported on {}",
260+
this.tcx.sess.target.os
261+
);
262+
}
263+
let [ptr, nmemb, size] =
264+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
265+
let ptr = this.read_pointer(ptr)?;
266+
let nmemb = this.read_target_usize(nmemb)?;
267+
let size = this.read_target_usize(size)?;
268+
// reallocarray checks a possible overflow and returns ENOMEM
269+
// if that happens.
270+
//
271+
// Linux: https://www.unix.com/man-page/linux/3/reallocarray/
272+
// FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=reallocarray
273+
match nmemb.checked_mul(size) {
274+
None => {
275+
let einval = this.eval_libc("ENOMEM");
276+
this.set_last_error(einval)?;
277+
this.write_null(dest)?;
278+
}
279+
Some(len) => {
280+
let res = this.realloc(ptr, len, MiriMemoryKind::C)?;
281+
this.write_pointer(res, dest)?;
282+
}
283+
}
284+
}
285+
253286
// Dynamic symbol loading
254287
"dlsym" => {
255288
let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -525,6 +558,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
525558
let result = this.getpid()?;
526559
this.write_scalar(Scalar::from_i32(result), dest)?;
527560
}
561+
"getentropy" => {
562+
// This function is non-standard but exists with the same signature and behavior on
563+
// Linux, macOS, and FreeBSD.
564+
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd") {
565+
throw_unsup_format!(
566+
"`getentropy` is not supported on {}",
567+
this.tcx.sess.target.os
568+
);
569+
}
570+
571+
let [buf, bufsize] =
572+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
573+
let buf = this.read_pointer(buf)?;
574+
let bufsize = this.read_target_usize(bufsize)?;
575+
576+
// getentropy sets errno to EIO when the buffer size exceeds 256 bytes.
577+
// FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html
578+
// Linux: https://man7.org/linux/man-pages/man3/getentropy.3.html
579+
// macOS: https://keith.github.io/xcode-man-pages/getentropy.2.html
580+
if bufsize > 256 {
581+
let err = this.eval_libc("EIO");
582+
this.set_last_error(err)?;
583+
this.write_scalar(Scalar::from_i32(-1), dest)?
584+
} else {
585+
this.gen_random(buf, bufsize)?;
586+
this.write_scalar(Scalar::from_i32(0), dest)?;
587+
}
588+
}
528589

529590
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
530591
// These shims are enabled only when the caller is in the standard library.
@@ -594,7 +655,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
594655
this.write_int(super::UID, dest)?;
595656
}
596657

597-
"getpwuid_r" if this.frame_in_std() => {
658+
"getpwuid_r"
659+
if this.frame_in_std() => {
598660
let [uid, pwd, buf, buflen, result] =
599661
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
600662
this.check_no_isolation("`getpwuid_r`")?;

src/tools/miri/src/shims/unix/freebsd/foreign_items.rs

+15
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4747
this.read_scalar(len)?,
4848
)?;
4949
}
50+
"getrandom" => {
51+
let [ptr, len, flags] =
52+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
53+
let ptr = this.read_pointer(ptr)?;
54+
let len = this.read_target_usize(len)?;
55+
let _flags = this.read_scalar(flags)?.to_i32()?;
56+
// flags on freebsd does not really matter
57+
// in practice, GRND_RANDOM does not particularly draw from /dev/random
58+
// since it is the same as to /dev/urandom.
59+
// GRND_INSECURE is only an alias of GRND_NONBLOCK, which
60+
// does not affect the RNG.
61+
// https://man.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2&n=1
62+
this.gen_random(ptr, len)?;
63+
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
64+
}
5065

5166
// errno
5267
"__error" => {

src/tools/miri/src/shims/unix/macos/foreign_items.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use shims::foreign_items::EmulateForeignItemResult;
66
use shims::unix::fs::EvalContextExt as _;
77
use shims::unix::thread::EvalContextExt as _;
88

9-
pub fn is_dyn_sym(name: &str) -> bool {
10-
matches!(name, "getentropy")
9+
pub fn is_dyn_sym(_name: &str) -> bool {
10+
false
1111
}
1212

1313
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -113,18 +113,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
113113
this.write_scalar(result, dest)?;
114114
}
115115

116-
// Random generation related shims
117-
"getentropy" => {
118-
let [buf, bufsize] =
119-
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
120-
let buf = this.read_pointer(buf)?;
121-
let bufsize = this.read_target_usize(bufsize)?;
122-
123-
this.gen_random(buf, bufsize)?;
124-
125-
this.write_scalar(Scalar::from_i32(0), dest)?; // KERN_SUCCESS
126-
}
127-
128116
// Access to command-line arguments
129117
"_NSGetArgc" => {
130118
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;

src/tools/miri/test_dependencies/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ edition = "2021"
1212
libc = "0.2"
1313
num_cpus = "1.10.1"
1414

15-
getrandom_1 = { package = "getrandom", version = "0.1" }
16-
getrandom = { version = "0.2", features = ["js"] }
15+
getrandom_01 = { package = "getrandom", version = "0.1" }
16+
getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] }
1717
rand = { version = "0.8", features = ["small_rng"] }
1818

1919
[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies]

src/tools/miri/tests/compiletest.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
7979
program.args.push(flag);
8080
}
8181

82+
// Add a test env var to do environment communication tests.
83+
program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
84+
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
85+
program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into())));
86+
8287
let mut config = Config {
8388
target: Some(target.to_owned()),
8489
stderr_filters: STDERR.clone(),
@@ -232,11 +237,6 @@ fn main() -> Result<()> {
232237
}
233238
}
234239

235-
// Add a test env var to do environment communication tests.
236-
env::set_var("MIRI_ENV_VAR_TEST", "0");
237-
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
238-
env::set_var("MIRI_TEMP", env::temp_dir());
239-
240240
ui(Mode::Pass, "tests/pass", &target, WithoutDependencies)?;
241241
ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies)?;
242242
ui(Mode::Panic, "tests/panic", &target, WithDependencies)?;
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// mac-os `getrandom_01` does some pointer shenanigans
2+
//@compile-flags: -Zmiri-permissive-provenance
3+
4+
/// Test direct calls of getrandom 0.1 and 0.2.
5+
/// Make sure they work even with isolation enabled (i.e., we do not hit a file-based fallback path).
6+
fn main() {
7+
let mut data = vec![0; 16];
8+
getrandom_01::getrandom(&mut data).unwrap();
9+
getrandom_02::getrandom(&mut data).unwrap();
10+
}

src/tools/miri/tests/pass-dep/getrandom_1.rs

-8
This file was deleted.

src/tools/miri/tests/pass-dep/random.rs src/tools/miri/tests/pass-dep/rand.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
//@compile-flags: -Zmiri-strict-provenance
2-
use rand::{rngs::SmallRng, Rng, SeedableRng};
2+
use rand::prelude::*;
33

4+
// Test using the `rand` crate to generate randomness.
45
fn main() {
5-
// Test `getrandom` directly.
6-
let mut data = vec![0; 16];
7-
getrandom::getrandom(&mut data).unwrap();
6+
// Fully deterministic seeding.
7+
let mut rng = SmallRng::seed_from_u64(42);
8+
let _val = rng.gen::<i32>();
9+
let _val = rng.gen::<isize>();
10+
let _val = rng.gen::<i128>();
811

912
// Try seeding with "real" entropy.
1013
let mut rng = SmallRng::from_entropy();

0 commit comments

Comments
 (0)