Skip to content

Commit efcbb94

Browse files
committed
Auto merge of #140436 - RalfJung:miri-sync, r=RalfJung
Miri subtree update r? `@ghost`
2 parents 4c83e55 + 929117e commit efcbb94

Some content is hidden

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

47 files changed

+799
-304
lines changed

src/tools/miri/.github/workflows/ci.yml

+37-35
Original file line numberDiff line numberDiff line change
@@ -89,41 +89,16 @@ jobs:
8989
# Check if all jobs that we depend on (in the needs array) were successful.
9090
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
9191
92-
cron-fail-notify:
93-
name: cronjob failure notification
92+
cron-rustc-pull:
93+
name: automatic pull from rustc
9494
runs-on: ubuntu-latest
9595
permissions:
9696
# The cronjob needs to be able to push to the repo...
9797
contents: write
9898
# ... and create a PR.
9999
pull-requests: write
100-
needs: [build, style, coverage]
101-
if: ${{ github.event_name == 'schedule' && failure() }}
100+
if: ${{ github.event_name == 'schedule' }}
102101
steps:
103-
# Send a Zulip notification
104-
- name: Install zulip-send
105-
run: pip3 install zulip
106-
- name: Send Zulip notification
107-
env:
108-
ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
109-
ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
110-
run: |
111-
~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
112-
--stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \
113-
--message 'Dear @*T-miri*,
114-
115-
It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed.
116-
117-
This likely means that rustc changed the miri directory and
118-
we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo).
119-
120-
Would you mind investigating this issue?
121-
122-
Thanks in advance!
123-
Sincerely,
124-
The Miri Cronjobs Bot'
125-
126-
# Attempt to auto-sync with rustc
127102
- uses: actions/checkout@v4
128103
with:
129104
fetch-depth: 256 # get a bit more of the history
@@ -143,18 +118,45 @@ jobs:
143118
run: |
144119
./miri toolchain
145120
./miri fmt --check || (./miri fmt && git commit -am "fmt")
146-
- name: Push changes to a branch
121+
- name: Push changes to a branch and create PR
147122
run: |
123+
# `git diff --exit-code` "succeeds" if the diff is empty.
124+
if git diff --exit-code HEAD^; then echo "Nothing changed in rustc, skipping PR"; exit 0; fi
125+
# The diff is non-empty, create a PR.
148126
BRANCH="rustup-$(date -u +%Y-%m-%d)"
149127
git switch -c $BRANCH
150128
git push -u origin $BRANCH
151-
- name: Create Pull Request
152-
run: |
153-
PR=$(gh pr create -B master --title 'Automatic Rustup' --body 'Please close and re-open this PR to trigger CI, then enable auto-merge.')
154-
~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
155-
--stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \
156-
--message "A PR doing a rustc-pull [has been automatically created]($PR) for your convenience."
129+
gh pr create -B master --title 'Automatic Rustup' --body 'Please close and re-open this PR to trigger CI, then enable auto-merge.'
157130
env:
158131
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
159132
ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
160133
ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
134+
135+
cron-fail-notify:
136+
name: cronjob failure notification
137+
runs-on: ubuntu-latest
138+
needs: [build, style, coverage]
139+
if: ${{ github.event_name == 'schedule' && failure() }}
140+
steps:
141+
# Send a Zulip notification
142+
- name: Install zulip-send
143+
run: pip3 install zulip
144+
- name: Send Zulip notification
145+
env:
146+
ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
147+
ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
148+
run: |
149+
~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
150+
--stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \
151+
--message 'Dear @*T-miri*,
152+
153+
It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed.
154+
155+
This likely means that rustc changed the miri directory and
156+
we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo).
157+
158+
Would you mind investigating this issue?
159+
160+
Thanks in advance!
161+
Sincerely,
162+
The Miri Cronjobs Bot'

src/tools/miri/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ Miri knows where it is supposed to start execution:
489489

490490
```rust
491491
#[cfg(miri)]
492-
#[no_mangle]
492+
#[unsafe(no_mangle)]
493493
fn miri_start(argc: isize, argv: *const *const u8) -> isize {
494494
// Call the actual start function that your project implements, based on your target's conventions.
495495
}

src/tools/miri/bench-cargo-miri/mse/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn read_i16(buffer: &[u8], index: usize) -> i16 {
1313
const SIZE: usize = size_of::<i16>();
1414
let mut bytes: [u8; SIZE] = [0u8; SIZE];
1515
bytes.copy_from_slice(&buffer[(index * SIZE)..(index * SIZE + SIZE)]);
16-
unsafe { std::mem::transmute(bytes) }
16+
i16::from_ne_bytes(bytes)
1717
}
1818

1919
fn mse(samples: usize, frame_buf: &[i16], buf_ref: &[u8]) -> f64 {

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1bc56185ee257ed829a0aea7abdc3b03c5fed887
1+
1b8ab72680f36e783af84c1a3c4f8508572bd9f9

src/tools/miri/src/alloc_addresses/mod.rs

+62-49
Original file line numberDiff line numberDiff line change
@@ -107,47 +107,6 @@ fn align_addr(addr: u64, align: u64) -> u64 {
107107

108108
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
109109
trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
110-
// Returns the exposed `AllocId` that corresponds to the specified addr,
111-
// or `None` if the addr is out of bounds
112-
fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option<AllocId> {
113-
let this = self.eval_context_ref();
114-
let global_state = this.machine.alloc_addresses.borrow();
115-
assert!(global_state.provenance_mode != ProvenanceMode::Strict);
116-
117-
// We always search the allocation to the right of this address. So if the size is structly
118-
// negative, we have to search for `addr-1` instead.
119-
let addr = if size >= 0 { addr } else { addr.saturating_sub(1) };
120-
let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr);
121-
122-
// Determine the in-bounds provenance for this pointer.
123-
let alloc_id = match pos {
124-
Ok(pos) => Some(global_state.int_to_ptr_map[pos].1),
125-
Err(0) => None,
126-
Err(pos) => {
127-
// This is the largest of the addresses smaller than `int`,
128-
// i.e. the greatest lower bound (glb)
129-
let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1];
130-
// This never overflows because `addr >= glb`
131-
let offset = addr - glb;
132-
// We require this to be strict in-bounds of the allocation. This arm is only
133-
// entered for addresses that are not the base address, so even zero-sized
134-
// allocations will get recognized at their base address -- but all other
135-
// allocations will *not* be recognized at their "end" address.
136-
let size = this.get_alloc_info(alloc_id).size;
137-
if offset < size.bytes() { Some(alloc_id) } else { None }
138-
}
139-
}?;
140-
141-
// We only use this provenance if it has been exposed.
142-
if global_state.exposed.contains(&alloc_id) {
143-
// This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
144-
debug_assert!(this.is_alloc_live(alloc_id));
145-
Some(alloc_id)
146-
} else {
147-
None
148-
}
149-
}
150-
151110
fn addr_from_alloc_id_uncached(
152111
&self,
153112
global_state: &mut GlobalStateInner,
@@ -242,11 +201,65 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
242201
interp_ok(base_addr)
243202
}
244203
}
204+
}
245205

206+
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
207+
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
208+
// Returns the `AllocId` that corresponds to the specified addr,
209+
// or `None` if the addr is out of bounds.
210+
// Setting `only_exposed_allocations` selects whether only exposed allocations are considered.
211+
fn alloc_id_from_addr(
212+
&self,
213+
addr: u64,
214+
size: i64,
215+
only_exposed_allocations: bool,
216+
) -> Option<AllocId> {
217+
let this = self.eval_context_ref();
218+
let global_state = this.machine.alloc_addresses.borrow();
219+
assert!(global_state.provenance_mode != ProvenanceMode::Strict);
220+
221+
// We always search the allocation to the right of this address. So if the size is strictly
222+
// negative, we have to search for `addr-1` instead.
223+
let addr = if size >= 0 { addr } else { addr.saturating_sub(1) };
224+
let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr);
225+
226+
// Determine the in-bounds provenance for this pointer.
227+
let alloc_id = match pos {
228+
Ok(pos) => Some(global_state.int_to_ptr_map[pos].1),
229+
Err(0) => None,
230+
Err(pos) => {
231+
// This is the largest of the addresses smaller than `int`,
232+
// i.e. the greatest lower bound (glb)
233+
let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1];
234+
// This never overflows because `addr >= glb`
235+
let offset = addr - glb;
236+
// We require this to be strict in-bounds of the allocation. This arm is only
237+
// entered for addresses that are not the base address, so even zero-sized
238+
// allocations will get recognized at their base address -- but all other
239+
// allocations will *not* be recognized at their "end" address.
240+
let size = this.get_alloc_info(alloc_id).size;
241+
if offset < size.bytes() { Some(alloc_id) } else { None }
242+
}
243+
}?;
244+
245+
// We only use this provenance if it has been exposed, or if the caller requested also non-exposed allocations
246+
if !only_exposed_allocations || global_state.exposed.contains(&alloc_id) {
247+
// This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
248+
debug_assert!(this.is_alloc_live(alloc_id));
249+
Some(alloc_id)
250+
} else {
251+
None
252+
}
253+
}
254+
255+
/// Returns the base address of an allocation, or an error if no base address could be found
256+
///
257+
/// # Panics
258+
/// If `memory_kind = None` and the `alloc_id` is not cached, meaning that the first call to this function per `alloc_id` must get the `memory_kind`.
246259
fn addr_from_alloc_id(
247260
&self,
248261
alloc_id: AllocId,
249-
memory_kind: MemoryKind,
262+
memory_kind: Option<MemoryKind>,
250263
) -> InterpResult<'tcx, u64> {
251264
let this = self.eval_context_ref();
252265
let mut global_state = this.machine.alloc_addresses.borrow_mut();
@@ -256,8 +269,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
256269
Some(&addr) => interp_ok(addr),
257270
None => {
258271
// First time we're looking for the absolute address of this allocation.
272+
let memory_kind =
273+
memory_kind.expect("memory_kind is required since alloc_id is not cached");
259274
let base_addr =
260-
self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?;
275+
this.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?;
261276
trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id);
262277

263278
// Store address in cache.
@@ -283,10 +298,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
283298
}
284299
}
285300
}
286-
}
287301

288-
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
289-
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
290302
fn expose_provenance(&self, provenance: Provenance) -> InterpResult<'tcx> {
291303
let this = self.eval_context_ref();
292304
let mut global_state = this.machine.alloc_addresses.borrow_mut();
@@ -365,7 +377,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
365377
let alloc_id = prov.alloc_id();
366378

367379
// Get a pointer to the beginning of this allocation.
368-
let base_addr = this.addr_from_alloc_id(alloc_id, kind)?;
380+
let base_addr = this.addr_from_alloc_id(alloc_id, Some(kind))?;
369381
let base_ptr = interpret::Pointer::new(
370382
Provenance::Concrete { alloc_id, tag },
371383
Size::from_bytes(base_addr),
@@ -388,7 +400,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
388400
// In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
389401
// This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
390402
// this function gets called before the first time `addr_from_alloc_id` gets called.
391-
this.addr_from_alloc_id(id, MiriMemoryKind::Global.into())?;
403+
this.addr_from_alloc_id(id, Some(MiriMemoryKind::Global.into()))?;
392404
// The memory we need here will have already been allocated during an earlier call to
393405
// `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
394406
// fetch the previously prepared bytes from `prepared_alloc_bytes`.
@@ -423,7 +435,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
423435
alloc_id
424436
} else {
425437
// A wildcard pointer.
426-
this.alloc_id_from_addr(addr.bytes(), size)?
438+
let only_exposed_allocations = true;
439+
this.alloc_id_from_addr(addr.bytes(), size, only_exposed_allocations)?
427440
};
428441

429442
// This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer

src/tools/miri/src/bin/miri.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
106106
} else {
107107
tcx.dcx().fatal(
108108
"`miri_start` must have the following signature:\n\
109-
fn miri_start(argc: isize, argv: *const *const u8) -> isize",
109+
fn miri_start(argc: isize, argv: *const *const u8) -> isize",
110110
);
111111
}
112112
} else {
@@ -115,7 +115,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
115115
Alternatively, you can export a `miri_start` function:\n\
116116
\n\
117117
#[cfg(miri)]\n\
118-
#[no_mangle]\n\
118+
#[unsafe(no_mangle)]\n\
119119
fn miri_start(argc: isize, argv: *const *const u8) -> isize {\
120120
\n // Call the actual start function that your project implements, based on your target's conventions.\n\
121121
}"

src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ fn all_read_accesses_commute() {
6161
// ... and produce the same final result.
6262
assert_eq!(
6363
loc12, loc21,
64-
"Read accesses {:?} followed by {:?} do not commute !",
65-
rel1, rel2
64+
"Read accesses {rel1:?} followed by {rel2:?} do not commute !"
6665
);
6766
}
6867
}
@@ -674,8 +673,8 @@ mod spurious_read {
674673
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
675674
let (x, y) = self.retag_permissions();
676675
write!(f, "{}; ", self.xy_rel)?;
677-
write!(f, "y: ({}); ", y,)?;
678-
write!(f, "retag x ({}); ", x)?;
676+
write!(f, "y: ({y}); ")?;
677+
write!(f, "retag x ({x}); ")?;
679678

680679
write!(f, "<arbitrary code>; <spurious read x>;")?;
681680
Ok(())
@@ -730,17 +729,17 @@ mod spurious_read {
730729
// protector.
731730
final_source
732731
.distinguishable::</*X*/ AllowRet, /*Y*/ AllowRet>(&final_target)
733-
.then_some(format!("{}", final_target))
732+
.then_some(format!("{final_target}"))
734733
} else {
735734
Some(format!("UB"))
736735
}
737736
};
738737
if let Some(final_target) = distinguishable {
739738
eprintln!(
740-
"For pattern '{}', inserting a spurious read through x makes the final state '{}' instead of '{}' which is observable",
741-
pat, final_target, final_source
739+
"For pattern '{pat}', inserting a spurious read through x makes the final state '{final_target}' \
740+
instead of '{final_source}' which is observable"
742741
);
743-
eprintln!(" (arbitrary code instanciated with '{}')", opaque);
742+
eprintln!(" (arbitrary code instanciated with '{opaque}')");
744743
err += 1;
745744
// We found an instanciation of the opaque code that makes this Pattern
746745
// fail, we don't really need to check the rest.

src/tools/miri/src/concurrency/data_race.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ impl AccessType {
381381
});
382382

383383
if let Some(ty) = ty {
384-
msg.push_str(&format!(" of type `{}`", ty));
384+
msg.push_str(&format!(" of type `{ty}`"));
385385
}
386386

387387
msg

src/tools/miri/src/helpers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10171017
}
10181018

10191019
/// Check that the given `caller_fn_abi` matches the expected ABI described by
1020-
/// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of
1020+
/// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and then returns the list of
10211021
/// arguments.
10221022
fn check_shim_abi<'a, const N: usize>(
10231023
&mut self,

src/tools/miri/src/machine.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,8 @@ impl<'tcx> MiriMachine<'tcx> {
721721
// Check if host target == the session target.
722722
if host_triple != target_triple {
723723
panic!(
724-
"calling external C functions in linked .so file requires host and target to be the same: host={}, target={}",
725-
host_triple,
726-
target_triple,
724+
"calling native C functions in linked .so file requires host and target to be the same: \
725+
host={host_triple}, target={target_triple}",
727726
);
728727
}
729728
// Note: it is the user's responsibility to provide a correct SO file.

0 commit comments

Comments
 (0)