Open
Description
Using the following flags
--force-warn clippy::ptr-as-ptr
this code:
//! Tests specific for <https://github.com/rust-lang/rust/issues/117945>: zero-sized operations.
use std::ptr;
fn main() {
// Null.
test_ptr(ptr::null_mut::<()>());
// No provenance.
test_ptr(ptr::without_provenance_mut::<()>(1));
// Out-of-bounds.
let mut b = Box::new(0i32);
let ptr = ptr::addr_of_mut!(*b) as *mut ();
test_ptr(ptr.wrapping_byte_add(2));
// Dangling (use-after-free).
drop(b);
test_ptr(ptr);
}
fn test_ptr(ptr: *mut ()) {
unsafe {
// Reads and writes.
let mut val = *ptr;
*ptr = val;
ptr.read();
ptr.write(());
// Memory access intrinsics.
// - memcpy (1st and 2nd argument)
ptr.copy_from_nonoverlapping(&(), 1);
ptr.copy_to_nonoverlapping(&mut val, 1);
// - memmove (1st and 2nd argument)
ptr.copy_from(&(), 1);
ptr.copy_to(&mut val, 1);
// - memset
ptr.write_bytes(0u8, 1);
// Offset.
let _ = ptr.offset(0);
let _ = ptr.offset(1); // this is still 0 bytes
// Distance.
let ptr = ptr.cast::<i32>();
ptr.offset_from(ptr);
// Distance from other "bad" pointers that have the same address, but different provenance. Some
// of this is library UB, but we don't want it to be language UB since that would violate
// provenance monotonicity: if we allow computing the distance between two ptrs with no
// provenance, we have to allow computing it between two ptrs with arbitrary provenance.
// - Distance from "no provenance"
ptr.offset_from(ptr::without_provenance_mut(ptr.addr()));
// - Distance from out-of-bounds pointer
let mut b = Box::new(0i32);
let other_ptr = ptr::addr_of_mut!(*b);
ptr.offset_from(other_ptr.with_addr(ptr.addr()));
// - Distance from use-after-free pointer
drop(b);
ptr.offset_from(other_ptr.with_addr(ptr.addr()));
}
}
caused the following diagnostics:
Blocking waiting for file lock on package cache
Blocking waiting for file lock on package cache
Blocking waiting for file lock on package cache
Blocking waiting for file lock on package cache
Checking _zero-sized-accesses-and-offsets v0.1.0 (/run/user/1085/tmp/dir.tp0UQIUgLzNJ/icemaker_clippyfix_tempdir.8nE15X1manAi/_zero-sized-accesses-and-offsets)
warning: `as` casting between raw pointers without changing their constness
--> src/main.rs:12:15
|
12 | let ptr = ptr::addr_of_mut!(*b) as *mut ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(&raw mut $place).cast::<()>()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr
= note: requested on the command line with `--force-warn clippy::ptr-as-ptr`
warning: `_zero-sized-accesses-and-offsets` (bin "_zero-sized-accesses-and-offsets") generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.18s
However after applying these diagnostics, the resulting code:
//! Tests specific for <https://github.com/rust-lang/rust/issues/117945>: zero-sized operations.
use std::ptr;
fn main() {
// Null.
test_ptr(ptr::null_mut::<()>());
// No provenance.
test_ptr(ptr::without_provenance_mut::<()>(1));
// Out-of-bounds.
let mut b = Box::new(0i32);
let ptr = (&raw mut $place).cast::<()>();
test_ptr(ptr.wrapping_byte_add(2));
// Dangling (use-after-free).
drop(b);
test_ptr(ptr);
}
fn test_ptr(ptr: *mut ()) {
unsafe {
// Reads and writes.
let mut val = *ptr;
*ptr = val;
ptr.read();
ptr.write(());
// Memory access intrinsics.
// - memcpy (1st and 2nd argument)
ptr.copy_from_nonoverlapping(&(), 1);
ptr.copy_to_nonoverlapping(&mut val, 1);
// - memmove (1st and 2nd argument)
ptr.copy_from(&(), 1);
ptr.copy_to(&mut val, 1);
// - memset
ptr.write_bytes(0u8, 1);
// Offset.
let _ = ptr.offset(0);
let _ = ptr.offset(1); // this is still 0 bytes
// Distance.
let ptr = ptr.cast::<i32>();
ptr.offset_from(ptr);
// Distance from other "bad" pointers that have the same address, but different provenance. Some
// of this is library UB, but we don't want it to be language UB since that would violate
// provenance monotonicity: if we allow computing the distance between two ptrs with no
// provenance, we have to allow computing it between two ptrs with arbitrary provenance.
// - Distance from "no provenance"
ptr.offset_from(ptr::without_provenance_mut(ptr.addr()));
// - Distance from out-of-bounds pointer
let mut b = Box::new(0i32);
let other_ptr = ptr::addr_of_mut!(*b);
ptr.offset_from(other_ptr.with_addr(ptr.addr()));
// - Distance from use-after-free pointer
drop(b);
ptr.offset_from(other_ptr.with_addr(ptr.addr()));
}
}
no longer compiled:
Checking _zero-sized-accesses-and-offsets v0.1.0 (/run/user/1085/tmp/dir.tp0UQIUgLzNJ/icemaker_clippyfix_tempdir.8nE15X1manAi/_zero-sized-accesses-and-offsets)
error: expected expression, found `$`
--> src/main.rs:12:25
|
12 | let ptr = (&raw mut $place).cast::<()>();
| ^ expected expression
error: could not compile `_zero-sized-accesses-and-offsets` (bin "_zero-sized-accesses-and-offsets") due to 1 previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `_zero-sized-accesses-and-offsets` (bin "_zero-sized-accesses-and-offsets" test) due to 1 previous error
Version:
rustc 1.90.0-nightly (f838cbc06 2025-07-08)
binary: rustc
commit-hash: f838cbc06de60819faff3413f374706b74824ca2
commit-date: 2025-07-08
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7