Skip to content

Commit da703af

Browse files
committed
Use real strict_provenance/exposed_provenance APIs on Rust 1.84+ and apply fuzzy_provenance_casts lint
1 parent 79fee52 commit da703af

File tree

10 files changed

+176
-68
lines changed

10 files changed

+176
-68
lines changed

bench/benches/imp/spinlock_fallback.rs

+16-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use core::{
1515
};
1616

1717
use super::fallback::utils::{Backoff, CachePadded};
18+
#[cfg(portable_atomic_no_strict_provenance)]
19+
use crate::utils::ptr::PtrExt;
1820

1921
struct Spinlock {
2022
state: AtomicUsize,
@@ -106,7 +108,7 @@ macro_rules! atomic_int {
106108
// SAFETY: any data races are prevented by the lock and the raw
107109
// pointer passed in is valid because we got it from a reference.
108110
unsafe {
109-
let _guard = lock(self.v.get() as usize);
111+
let _guard = lock(self.v.get().addr());
110112
self.v.get().read()
111113
}
112114
}
@@ -118,7 +120,7 @@ macro_rules! atomic_int {
118120
// SAFETY: any data races are prevented by the lock and the raw
119121
// pointer passed in is valid because we got it from a reference.
120122
unsafe {
121-
let _guard = lock(self.v.get() as usize);
123+
let _guard = lock(self.v.get().addr());
122124
self.v.get().write(val)
123125
}
124126
}
@@ -128,7 +130,7 @@ macro_rules! atomic_int {
128130
// SAFETY: any data races are prevented by the lock and the raw
129131
// pointer passed in is valid because we got it from a reference.
130132
unsafe {
131-
let _guard = lock(self.v.get() as usize);
133+
let _guard = lock(self.v.get().addr());
132134
let prev = self.v.get().read();
133135
self.v.get().write(val);
134136
prev
@@ -148,7 +150,7 @@ macro_rules! atomic_int {
148150
// SAFETY: any data races are prevented by the lock and the raw
149151
// pointer passed in is valid because we got it from a reference.
150152
unsafe {
151-
let _guard = lock(self.v.get() as usize);
153+
let _guard = lock(self.v.get().addr());
152154
let prev = self.v.get().read();
153155
if prev == current {
154156
self.v.get().write(new);
@@ -176,7 +178,7 @@ macro_rules! atomic_int {
176178
// SAFETY: any data races are prevented by the lock and the raw
177179
// pointer passed in is valid because we got it from a reference.
178180
unsafe {
179-
let _guard = lock(self.v.get() as usize);
181+
let _guard = lock(self.v.get().addr());
180182
let prev = self.v.get().read();
181183
self.v.get().write(prev.wrapping_add(val));
182184
prev
@@ -188,7 +190,7 @@ macro_rules! atomic_int {
188190
// SAFETY: any data races are prevented by the lock and the raw
189191
// pointer passed in is valid because we got it from a reference.
190192
unsafe {
191-
let _guard = lock(self.v.get() as usize);
193+
let _guard = lock(self.v.get().addr());
192194
let prev = self.v.get().read();
193195
self.v.get().write(prev.wrapping_sub(val));
194196
prev
@@ -200,7 +202,7 @@ macro_rules! atomic_int {
200202
// SAFETY: any data races are prevented by the lock and the raw
201203
// pointer passed in is valid because we got it from a reference.
202204
unsafe {
203-
let _guard = lock(self.v.get() as usize);
205+
let _guard = lock(self.v.get().addr());
204206
let prev = self.v.get().read();
205207
self.v.get().write(prev & val);
206208
prev
@@ -212,7 +214,7 @@ macro_rules! atomic_int {
212214
// SAFETY: any data races are prevented by the lock and the raw
213215
// pointer passed in is valid because we got it from a reference.
214216
unsafe {
215-
let _guard = lock(self.v.get() as usize);
217+
let _guard = lock(self.v.get().addr());
216218
let prev = self.v.get().read();
217219
self.v.get().write(!(prev & val));
218220
prev
@@ -224,7 +226,7 @@ macro_rules! atomic_int {
224226
// SAFETY: any data races are prevented by the lock and the raw
225227
// pointer passed in is valid because we got it from a reference.
226228
unsafe {
227-
let _guard = lock(self.v.get() as usize);
229+
let _guard = lock(self.v.get().addr());
228230
let prev = self.v.get().read();
229231
self.v.get().write(prev | val);
230232
prev
@@ -236,7 +238,7 @@ macro_rules! atomic_int {
236238
// SAFETY: any data races are prevented by the lock and the raw
237239
// pointer passed in is valid because we got it from a reference.
238240
unsafe {
239-
let _guard = lock(self.v.get() as usize);
241+
let _guard = lock(self.v.get().addr());
240242
let prev = self.v.get().read();
241243
self.v.get().write(prev ^ val);
242244
prev
@@ -248,7 +250,7 @@ macro_rules! atomic_int {
248250
// SAFETY: any data races are prevented by the lock and the raw
249251
// pointer passed in is valid because we got it from a reference.
250252
unsafe {
251-
let _guard = lock(self.v.get() as usize);
253+
let _guard = lock(self.v.get().addr());
252254
let prev = self.v.get().read();
253255
self.v.get().write(core::cmp::max(prev, val));
254256
prev
@@ -260,7 +262,7 @@ macro_rules! atomic_int {
260262
// SAFETY: any data races are prevented by the lock and the raw
261263
// pointer passed in is valid because we got it from a reference.
262264
unsafe {
263-
let _guard = lock(self.v.get() as usize);
265+
let _guard = lock(self.v.get().addr());
264266
let prev = self.v.get().read();
265267
self.v.get().write(core::cmp::min(prev, val));
266268
prev
@@ -272,7 +274,7 @@ macro_rules! atomic_int {
272274
// SAFETY: any data races are prevented by the lock and the raw
273275
// pointer passed in is valid because we got it from a reference.
274276
unsafe {
275-
let _guard = lock(self.v.get() as usize);
277+
let _guard = lock(self.v.get().addr());
276278
let prev = self.v.get().read();
277279
self.v.get().write(!prev);
278280
prev
@@ -288,7 +290,7 @@ macro_rules! atomic_int {
288290
// SAFETY: any data races are prevented by the lock and the raw
289291
// pointer passed in is valid because we got it from a reference.
290292
unsafe {
291-
let _guard = lock(self.v.get() as usize);
293+
let _guard = lock(self.v.get().addr());
292294
let prev = self.v.get().read();
293295
self.v.get().write(prev.wrapping_neg());
294296
prev

build.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn main() {
5353
// Custom cfgs set by build script. Not public API.
5454
// grep -F 'cargo:rustc-cfg=' build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
5555
println!(
56-
"cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_offset_of,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)"
56+
"cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_offset_of,portable_atomic_no_strict_provenance,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)"
5757
);
5858
// TODO: handle multi-line target_feature_fallback
5959
// grep -F 'target_feature_fallback("' build.rs | grep -Ev '^ *//' | sed -E 's/^.*target_feature_fallback\(//; s/",.*$/"/' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
@@ -126,6 +126,10 @@ fn main() {
126126
if !version.probe(83, 2024, 9, 15) {
127127
println!("cargo:rustc-cfg=portable_atomic_no_const_mut_refs");
128128
}
129+
// strict_provenance/exposed_provenance APIs stabilized in Rust 1.84 (nightly-2024-10-22): https://github.com/rust-lang/rust/pull/130350
130+
if !version.probe(84, 2024, 10, 21) {
131+
println!("cargo:rustc-cfg=portable_atomic_no_strict_provenance");
132+
}
129133

130134
// asm! on AArch64, Arm, RISC-V, x86, and x86_64 stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728
131135
let no_asm = !version.probe(59, 2021, 12, 15);

portable-atomic-util/build.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ fn main() {
3131

3232
if version.minor >= 80 {
3333
// Custom cfgs set by build script. Not public API.
34-
// grep -F 'cargo:rustc-cfg=' build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
34+
// grep -F 'cargo:rustc-cfg=' portable-atomic-util/build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/'
3535
println!(
36-
"cargo:rustc-check-cfg=cfg(portable_atomic_no_alloc,portable_atomic_no_alloc_layout_extras,portable_atomic_no_core_unwind_safe,portable_atomic_no_error_in_core,portable_atomic_no_futures_api,portable_atomic_no_io_safety,portable_atomic_no_io_vec,portable_atomic_no_maybe_uninit,portable_atomic_no_min_const_generics,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_sanitize_thread)"
36+
"cargo:rustc-check-cfg=cfg(portable_atomic_no_alloc,portable_atomic_no_alloc_layout_extras,portable_atomic_no_core_unwind_safe,portable_atomic_no_error_in_core,portable_atomic_no_futures_api,portable_atomic_no_io_safety,portable_atomic_no_io_vec,portable_atomic_no_maybe_uninit,portable_atomic_no_min_const_generics,portable_atomic_no_strict_provenance,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_sanitize_thread)"
3737
);
3838
}
3939

@@ -85,6 +85,10 @@ fn main() {
8585
if !version.probe(81, 2024, 6, 8) {
8686
println!("cargo:rustc-cfg=portable_atomic_no_error_in_core");
8787
}
88+
// strict_provenance/exposed_provenance APIs stabilized in Rust 1.84 (nightly-2024-10-22): https://github.com/rust-lang/rust/pull/130350
89+
if !version.probe(84, 2024, 10, 21) {
90+
println!("cargo:rustc-cfg=portable_atomic_no_strict_provenance");
91+
}
8892

8993
if version.nightly {
9094
// `cfg(sanitize = "..")` is not stabilized.

portable-atomic-util/src/arc.rs

+35-3
Original file line numberDiff line numberDiff line change
@@ -3020,7 +3020,7 @@ fn abort() -> ! {
30203020
}
30213021

30223022
fn is_dangling<T: ?Sized>(ptr: *const T) -> bool {
3023-
ptr as *const () as usize == usize::MAX
3023+
(ptr as *const ()).addr() == usize::MAX
30243024
}
30253025

30263026
// Based on unstable alloc::alloc::Global.
@@ -3061,8 +3061,18 @@ impl Global {
30613061
}
30623062
}
30633063

3064-
// TODO: use stabilized core::ptr strict_provenance helpers https://github.com/rust-lang/rust/pull/130350
3064+
#[cfg(portable_atomic_no_strict_provenance)]
3065+
use self::strict::PtrExt;
3066+
3067+
// strict_provenance polyfill for pre-1.84 rustc.
30653068
mod strict {
3069+
#[cfg(portable_atomic_no_strict_provenance)]
3070+
use core::mem;
3071+
#[cfg(not(portable_atomic_no_strict_provenance))]
3072+
#[allow(unused_imports)]
3073+
pub(crate) use core::ptr::without_provenance_mut;
3074+
3075+
#[cfg(portable_atomic_no_strict_provenance)]
30663076
#[inline(always)]
30673077
#[must_use]
30683078
pub(super) const fn without_provenance_mut<T>(addr: usize) -> *mut T {
@@ -3073,7 +3083,7 @@ mod strict {
30733083
// pointer).
30743084
#[cfg(miri)]
30753085
unsafe {
3076-
core::mem::transmute(addr)
3086+
mem::transmute(addr)
30773087
}
30783088
// const transmute requires Rust 1.56.
30793089
#[cfg(not(miri))]
@@ -3111,4 +3121,26 @@ mod strict {
31113121
// SAFETY: the caller must uphold the safety contract for `sub`.
31123122
unsafe { with_metadata_of((ptr as *mut u8).sub(count), ptr) }
31133123
}
3124+
3125+
#[cfg(portable_atomic_no_strict_provenance)]
3126+
pub(crate) trait PtrExt<T: ?Sized>: Copy {
3127+
#[must_use]
3128+
fn addr(self) -> usize;
3129+
}
3130+
#[cfg(portable_atomic_no_strict_provenance)]
3131+
impl<T: ?Sized> PtrExt<T> for *const T {
3132+
#[must_use]
3133+
#[inline(always)]
3134+
fn addr(self) -> usize {
3135+
// A pointer-to-integer transmute currently has exactly the right semantics: it returns the
3136+
// address without exposing the provenance. Note that this is *not* a stable guarantee about
3137+
// transmute semantics, it relies on sysroot crates having special status.
3138+
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
3139+
// provenance).
3140+
#[allow(clippy::transmutes_expressible_as_ptr_casts)]
3141+
unsafe {
3142+
mem::transmute(self as *const ())
3143+
}
3144+
}
3145+
}
31143146
}

portable-atomic-util/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ RUSTFLAGS="--cfg portable_atomic_unstable_coerce_unsized" cargo ...
8484
clippy::std_instead_of_alloc,
8585
clippy::std_instead_of_core,
8686
)]
87+
#![cfg_attr(portable_atomic_no_strict_provenance, allow(unstable_name_collisions))]
8788
#![allow(clippy::inline_always)]
8889
// docs.rs only (cfg is enabled by docs.rs, not build script)
8990
#![cfg_attr(docsrs, feature(doc_cfg))]

src/imp/atomic64/arm_linux.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn __kuser_helper_version() -> i32 {
4242
// SAFETY: core assumes that at least __kuser_memory_barrier (__kuser_helper_version >= 3,
4343
// kernel version 2.6.15+) is available on this platform. __kuser_helper_version
4444
// is always available on such a platform.
45-
v = unsafe { (KUSER_HELPER_VERSION as *const i32).read() };
45+
v = unsafe { crate::utils::ptr::with_exposed_provenance::<i32>(KUSER_HELPER_VERSION).read() };
4646
CACHE.store(v, Ordering::Relaxed);
4747
v
4848
}
@@ -61,7 +61,7 @@ unsafe fn __kuser_cmpxchg64(old_val: *const u64, new_val: *const u64, ptr: *mut
6161
// SAFETY: the caller must uphold the safety contract.
6262
unsafe {
6363
let f: extern "C" fn(*const u64, *const u64, *mut u64) -> u32 =
64-
mem::transmute(KUSER_CMPXCHG64 as *const ());
64+
mem::transmute(crate::utils::ptr::with_exposed_provenance::<()>(KUSER_CMPXCHG64));
6565
f(old_val, new_val, ptr) == 0
6666
}
6767
}

0 commit comments

Comments
 (0)