Skip to content

Commit 174038b

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 174038b

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,28 @@ 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(
140+
ptr: *const (),
141+
align: usize,
142+
) -> bool {
143+
// This is just for safety checks so we can const_eval_select.
144+
const_eval_select!(
145+
@capture { ptr: *const (), align: usize } -> bool:
146+
if const {
147+
true
148+
} else {
149+
ptr.is_aligned_to(align)
150+
}
151+
)
152+
}
153+
132154
#[inline]
133155
pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool {
134156
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };

0 commit comments

Comments
 (0)