Skip to content

Commit f514bd3

Browse files
authored
miri: don't use int2ptr casts for invalid pointers (#553)
1 parent 28a1eab commit f514bd3

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

src/bytes_mut.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ impl BytesMut {
253253

254254
let ptr = self.ptr.as_ptr();
255255
let len = self.len;
256-
let data = AtomicPtr::new(self.data as _);
256+
let data = AtomicPtr::new(self.data.cast());
257257
mem::forget(self);
258258
unsafe { Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE) }
259259
}
@@ -613,7 +613,7 @@ impl BytesMut {
613613
}
614614

615615
debug_assert_eq!(kind, KIND_ARC);
616-
let shared: *mut Shared = self.data as _;
616+
let shared: *mut Shared = self.data;
617617

618618
// Reserving involves abandoning the currently shared buffer and
619619
// allocating a new vector with the requested capacity.
@@ -692,7 +692,7 @@ impl BytesMut {
692692

693693
// Update self
694694
let data = (original_capacity_repr << ORIGINAL_CAPACITY_OFFSET) | KIND_VEC;
695-
self.data = data as _;
695+
self.data = invalid_ptr(data);
696696
self.ptr = vptr(v.as_mut_ptr());
697697
self.len = v.len();
698698
self.cap = v.capacity();
@@ -723,7 +723,7 @@ impl BytesMut {
723723
// Reserved above
724724
debug_assert!(dst.len() >= cnt);
725725

726-
ptr::copy_nonoverlapping(extend.as_ptr(), dst.as_mut_ptr() as *mut u8, cnt);
726+
ptr::copy_nonoverlapping(extend.as_ptr(), dst.as_mut_ptr(), cnt);
727727
}
728728

729729
unsafe {
@@ -788,7 +788,7 @@ impl BytesMut {
788788
ptr,
789789
len,
790790
cap,
791-
data: data as *mut _,
791+
data: invalid_ptr(data),
792792
}
793793
}
794794

@@ -909,7 +909,7 @@ impl BytesMut {
909909
// always succeed.
910910
debug_assert_eq!(shared as usize & KIND_MASK, KIND_ARC);
911911

912-
self.data = shared as _;
912+
self.data = shared;
913913
}
914914

915915
/// Makes an exact shallow clone of `self`.
@@ -942,7 +942,7 @@ impl BytesMut {
942942
debug_assert_eq!(self.kind(), KIND_VEC);
943943
debug_assert!(pos <= MAX_VEC_POS);
944944

945-
self.data = ((pos << VEC_POS_OFFSET) | (prev & NOT_VEC_POS_MASK)) as *mut _;
945+
self.data = invalid_ptr((pos << VEC_POS_OFFSET) | (prev & NOT_VEC_POS_MASK));
946946
}
947947

948948
#[inline]
@@ -968,7 +968,7 @@ impl Drop for BytesMut {
968968
let _ = rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off);
969969
}
970970
} else if kind == KIND_ARC {
971-
unsafe { release_shared(self.data as _) };
971+
unsafe { release_shared(self.data) };
972972
}
973973
}
974974
}
@@ -1549,6 +1549,18 @@ fn vptr(ptr: *mut u8) -> NonNull<u8> {
15491549
}
15501550
}
15511551

1552+
/// Returns a dangling pointer with the given address. This is used to store
1553+
/// integer data in pointer fields.
1554+
///
1555+
/// It is equivalent to `addr as *mut T`, but this fails on miri when strict
1556+
/// provenance checking is enabled.
1557+
#[inline]
1558+
fn invalid_ptr<T>(addr: usize) -> *mut T {
1559+
let ptr = core::ptr::null_mut::<u8>().wrapping_add(addr);
1560+
debug_assert_eq!(ptr as usize, addr);
1561+
ptr.cast::<T>()
1562+
}
1563+
15521564
unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize) -> Vec<u8> {
15531565
let ptr = ptr.offset(-(off as isize));
15541566
len += off;
@@ -1568,7 +1580,7 @@ unsafe fn shared_v_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> By
15681580
let shared = data.load(Ordering::Relaxed) as *mut Shared;
15691581
increment_shared(shared);
15701582

1571-
let data = AtomicPtr::new(shared as _);
1583+
let data = AtomicPtr::new(shared as *mut ());
15721584
Bytes::with_vtable(ptr, len, data, &SHARED_VTABLE)
15731585
}
15741586

tests/test_bytes_vec_alloc.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Ledger {
4545
if entry_ptr
4646
.compare_exchange(
4747
ptr,
48-
usize::MAX as *mut u8,
48+
invalid_ptr(usize::MAX),
4949
Ordering::SeqCst,
5050
Ordering::SeqCst,
5151
)
@@ -103,3 +103,12 @@ fn test_bytes_truncate_and_advance() {
103103
bytes.advance(1);
104104
drop(bytes);
105105
}
106+
107+
/// Returns a dangling pointer with the given address. This is used to store
108+
/// integer data in pointer fields.
109+
#[inline]
110+
fn invalid_ptr<T>(addr: usize) -> *mut T {
111+
let ptr = std::ptr::null_mut::<u8>().wrapping_add(addr);
112+
debug_assert_eq!(ptr as usize, addr);
113+
ptr.cast::<T>()
114+
}

0 commit comments

Comments
 (0)