about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-07-20 08:56:05 +0200
committerGitHub <noreply@github.com>2025-07-20 08:56:05 +0200
commit6d7d366fd3c1ae6ce722e46d1fecfdf258d02f9d (patch)
tree8d13623ca86e733418a5009fe6751f91150f4702 /tests
parent6707bf0f59485cf054ac1095725df43220e4be20 (diff)
parent8a8717e971dbdc6155506a4332e9ce8ef9151caa (diff)
downloadrust-6d7d366fd3c1ae6ce722e46d1fecfdf258d02f9d.tar.gz
rust-6d7d366fd3c1ae6ce722e46d1fecfdf258d02f9d.zip
Rollup merge of #141260 - LuigiPiucco:volatile-null, r=RalfJung
Allow volatile access to non-Rust memory, including address 0

This PR relaxes the `ub_check` in the `read_volatile`/`write_volatile` pointer operations to allow passing null. This is needed to support processors which hard-code peripheral registers on address 0, like the AVR chip ATtiny1626. LLVM understands this as valid and handles it correctly, as tested in my [PR to add a note about it](https://github.com/llvm/llvm-project/pull/139803/commits/6387c82255c56d3035d249eb54110695e76b8030#diff-81bbb96298c32fa901beb82ab3b97add27a410c01d577c1f8c01000ed2055826) (rustc generates the same LLVM IR as expected there when this PR is applied, and consequently the same AVR assembly).

Follow-up and implementation of the discussions in:
- https://internals.rust-lang.org/t/pre-rfc-conditionally-supported-volatile-access-to-address-0/12881/7
- https://github.com/Rahix/avr-device/pull/185;
- [#t-lang > Adding the possibility of volatile access to address 0](https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/Adding.20the.20possibility.20of.20volatile.20access.20to.20address.200/with/513303502)
- https://discourse.llvm.org/t/rfc-volatile-access-to-non-dereferenceable-memory-may-be-well-defined/86303

r? ````@RalfJung````

Also fixes https://github.com/rust-lang/unsafe-code-guidelines/issues/29 (about as good as it'll get, null will likely never be a "normal" address in Rust)
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/lint/invalid_null_args.rs5
-rw-r--r--tests/ui/lint/invalid_null_args.stderr58
-rw-r--r--tests/ui/precondition-checks/read_volatile.rs6
-rw-r--r--tests/ui/precondition-checks/write_volatile.rs6
4 files changed, 18 insertions, 57 deletions
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
index f40f06a0d36..ee29d622ad7 100644
--- a/tests/ui/lint/invalid_null_args.rs
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -58,10 +58,9 @@ unsafe fn null_ptr() {
     let _a: A = ptr::read_unaligned(ptr::null_mut());
     //~^ ERROR calling this function with a null pointer is undefined behavior
 
+    // These two should *not* fire the lint.
     let _a: A = ptr::read_volatile(ptr::null());
-    //~^ ERROR calling this function with a null pointer is undefined behavior
     let _a: A = ptr::read_volatile(ptr::null_mut());
-    //~^ ERROR calling this function with a null pointer is undefined behavior
 
     let _a: A = ptr::replace(ptr::null_mut(), v);
     //~^ ERROR calling this function with a null pointer is undefined behavior
@@ -82,8 +81,8 @@ unsafe fn null_ptr() {
     ptr::write_unaligned(ptr::null_mut(), v);
     //~^ ERROR calling this function with a null pointer is undefined behavior
 
+    // This one should *not* fire the lint.
     ptr::write_volatile(ptr::null_mut(), v);
-    //~^ ERROR calling this function with a null pointer is undefined behavior
 
     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
     //~^ ERROR calling this function with a null pointer is undefined behavior
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
index 11c6270cfb7..028bd7051dc 100644
--- a/tests/ui/lint/invalid_null_args.stderr
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -164,27 +164,7 @@ LL |     let _a: A = ptr::read_unaligned(ptr::null_mut());
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:61:17
-   |
-LL |     let _a: A = ptr::read_volatile(ptr::null());
-   |                 ^^^^^^^^^^^^^^^^^^^-----------^
-   |                                    |
-   |                                    null pointer originates from here
-   |
-   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:63:17
-   |
-LL |     let _a: A = ptr::read_volatile(ptr::null_mut());
-   |                 ^^^^^^^^^^^^^^^^^^^---------------^
-   |                                    |
-   |                                    null pointer originates from here
-   |
-   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:66:17
+  --> $DIR/invalid_null_args.rs:65:17
    |
 LL |     let _a: A = ptr::replace(ptr::null_mut(), v);
    |                 ^^^^^^^^^^^^^---------------^^^^
@@ -194,7 +174,7 @@ LL |     let _a: A = ptr::replace(ptr::null_mut(), v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:69:5
+  --> $DIR/invalid_null_args.rs:68:5
    |
 LL |     ptr::swap::<A>(ptr::null_mut(), &mut v);
    |     ^^^^^^^^^^^^^^^---------------^^^^^^^^^
@@ -204,7 +184,7 @@ LL |     ptr::swap::<A>(ptr::null_mut(), &mut v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:71:5
+  --> $DIR/invalid_null_args.rs:70:5
    |
 LL |     ptr::swap::<A>(&mut v, ptr::null_mut());
    |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^
@@ -214,7 +194,7 @@ LL |     ptr::swap::<A>(&mut v, ptr::null_mut());
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:74:5
+  --> $DIR/invalid_null_args.rs:73:5
    |
 LL |     ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^
@@ -224,7 +204,7 @@ LL |     ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:76:5
+  --> $DIR/invalid_null_args.rs:75:5
    |
 LL |     ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -234,7 +214,7 @@ LL |     ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:79:5
+  --> $DIR/invalid_null_args.rs:78:5
    |
 LL |     ptr::write(ptr::null_mut(), v);
    |     ^^^^^^^^^^^---------------^^^^
@@ -244,7 +224,7 @@ LL |     ptr::write(ptr::null_mut(), v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:82:5
+  --> $DIR/invalid_null_args.rs:81:5
    |
 LL |     ptr::write_unaligned(ptr::null_mut(), v);
    |     ^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -254,17 +234,7 @@ LL |     ptr::write_unaligned(ptr::null_mut(), v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:85:5
-   |
-LL |     ptr::write_volatile(ptr::null_mut(), v);
-   |     ^^^^^^^^^^^^^^^^^^^^---------------^^^^
-   |                         |
-   |                         null pointer originates from here
-   |
-   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:88:5
+  --> $DIR/invalid_null_args.rs:87:5
    |
 LL |     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^
@@ -274,7 +244,7 @@ LL |     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:93:18
+  --> $DIR/invalid_null_args.rs:92:18
    |
 LL |     let _a: u8 = ptr::read(const_ptr);
    |                  ^^^^^^^^^^^^^^^^^^^^
@@ -287,7 +257,7 @@ LL |     let null_ptr = ptr::null_mut();
    |                    ^^^^^^^^^^^^^^^
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:100:5
+  --> $DIR/invalid_null_args.rs:99:5
    |
 LL |     std::slice::from_raw_parts::<()>(ptr::null(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@@ -297,7 +267,7 @@ LL |     std::slice::from_raw_parts::<()>(ptr::null(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:102:5
+  --> $DIR/invalid_null_args.rs:101:5
    |
 LL |     std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@@ -307,7 +277,7 @@ LL |     std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:104:5
+  --> $DIR/invalid_null_args.rs:103:5
    |
 LL |     std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -317,7 +287,7 @@ LL |     std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:106:5
+  --> $DIR/invalid_null_args.rs:105:5
    |
 LL |     std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -326,5 +296,5 @@ LL |     std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
    |
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
-error: aborting due to 31 previous errors
+error: aborting due to 28 previous errors
 
diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs
index fa1c2c827d7..33350dfbc4f 100644
--- a/tests/ui/precondition-checks/read_volatile.rs
+++ b/tests/ui/precondition-checks/read_volatile.rs
@@ -1,9 +1,7 @@
 //@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
-//@ revisions: null misaligned
-
-#![allow(invalid_null_arguments)]
+//@ revisions: misaligned
 
 use std::ptr;
 
@@ -11,8 +9,6 @@ fn main() {
     let src = [0u16; 2];
     let src = src.as_ptr();
     unsafe {
-        #[cfg(null)]
-        ptr::read_volatile(ptr::null::<u8>());
         #[cfg(misaligned)]
         ptr::read_volatile(src.byte_add(1));
     }
diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs
index 25107871c39..d6ad6320e41 100644
--- a/tests/ui/precondition-checks/write_volatile.rs
+++ b/tests/ui/precondition-checks/write_volatile.rs
@@ -1,9 +1,7 @@
 //@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
-//@ revisions: null misaligned
-
-#![allow(invalid_null_arguments)]
+//@ revisions: misaligned
 
 use std::ptr;
 
@@ -11,8 +9,6 @@ fn main() {
     let mut dst = [0u16; 2];
     let mut dst = dst.as_mut_ptr();
     unsafe {
-        #[cfg(null)]
-        ptr::write_volatile(ptr::null_mut::<u8>(), 1u8);
         #[cfg(misaligned)]
         ptr::write_volatile(dst.byte_add(1), 1u16);
     }