Skip to content

Commit 0559f50

Browse files
committed
fix: don't panic on volatile access to null
According to https://discourse.llvm.org/t/rfc-volatile-access-to-non-dereferenceable-memory-may-be-well-defined/86303/4, LLVM allows volatile operations on null and handles it correctly. This should be allowed in Rust as well, because I/O memory may be hard-coded to address 0 in some cases, like the AVR chip ATtiny1626.
1 parent 7068c8b commit 0559f50

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

library/core/src/ptr/mod.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,12 +1813,11 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
18131813
unsafe {
18141814
ub_checks::assert_unsafe_precondition!(
18151815
check_language_ub,
1816-
"ptr::read_volatile requires that the pointer argument is aligned and non-null",
1816+
"ptr::read_volatile requires that the pointer argument is aligned",
18171817
(
18181818
addr: *const () = src as *const (),
18191819
align: usize = align_of::<T>(),
1820-
is_zst: bool = T::IS_ZST,
1821-
) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
1820+
) => ub_checks::maybe_is_aligned(addr, align)
18221821
);
18231822
intrinsics::volatile_load(src)
18241823
}
@@ -1893,12 +1892,11 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
18931892
unsafe {
18941893
ub_checks::assert_unsafe_precondition!(
18951894
check_language_ub,
1896-
"ptr::write_volatile requires that the pointer argument is aligned and non-null",
1895+
"ptr::write_volatile requires that the pointer argument is aligned",
18971896
(
18981897
addr: *mut () = dst as *mut (),
18991898
align: usize = align_of::<T>(),
1900-
is_zst: bool = T::IS_ZST,
1901-
) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
1899+
) => ub_checks::maybe_is_aligned(addr, align)
19021900
);
19031901
intrinsics::volatile_store(dst, src);
19041902
}

library/core/src/ub_checks.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,25 @@ pub(crate) const fn maybe_is_aligned_and_not_null(
129129
)
130130
}
131131

132+
/// Checks whether `ptr` is properly aligned with respect to the given alignment.
133+
///
134+
/// In `const` this is approximate and can fail spuriously. It is primarily intended
135+
/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
136+
/// check is anyway not executed in `const`.
137+
#[inline]
138+
#[rustc_allow_const_fn_unstable(const_eval_select)]
139+
pub(crate) const fn maybe_is_aligned(ptr: *const (), align: usize) -> bool {
140+
// This is just for safety checks so we can const_eval_select.
141+
const_eval_select!(
142+
@capture { ptr: *const (), align: usize } -> bool:
143+
if const {
144+
true
145+
} else {
146+
ptr.is_aligned_to(align)
147+
}
148+
)
149+
}
150+
132151
#[inline]
133152
pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool {
134153
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };

0 commit comments

Comments
 (0)