Skip to content

Commit 2575cb2

Browse files
Darksonnlelongg
authored andcommitted
miri: don't use int2ptr casts for invalid pointers (tokio-rs#553)
1 parent 80f7c88 commit 2575cb2

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
@@ -46,7 +46,7 @@ impl Ledger {
4646
if entry_ptr
4747
.compare_exchange(
4848
ptr,
49-
usize::MAX as *mut u8,
49+
invalid_ptr(usize::MAX),
5050
Ordering::SeqCst,
5151
Ordering::SeqCst,
5252
)
@@ -104,3 +104,12 @@ fn test_bytes_truncate_and_advance() {
104104
bytes.advance(1);
105105
drop(bytes);
106106
}
107+
108+
/// Returns a dangling pointer with the given address. This is used to store
109+
/// integer data in pointer fields.
110+
#[inline]
111+
fn invalid_ptr<T>(addr: usize) -> *mut T {
112+
let ptr = std::ptr::null_mut::<u8>().wrapping_add(addr);
113+
debug_assert_eq!(ptr as usize, addr);
114+
ptr.cast::<T>()
115+
}

0 commit comments

Comments
 (0)