diff --git a/tokio-util/src/lib.rs b/tokio-util/src/lib.rs index fd14a8ac947..e4876a58a80 100644 --- a/tokio-util/src/lib.rs +++ b/tokio-util/src/lib.rs @@ -115,6 +115,9 @@ mod util { let n = { let dst = buf.chunk_mut(); + + // Safety: `chunk_mut()` returns a `&mut UninitSlice`, and `UninitSlice` is a + // transparent wrapper around `[MaybeUninit]`. let dst = unsafe { &mut *(dst as *mut _ as *mut [MaybeUninit]) }; let mut buf = ReadBuf::uninit(dst); let ptr = buf.filled().as_ptr(); diff --git a/tokio-util/src/udp/frame.rs b/tokio-util/src/udp/frame.rs index d900fd7691e..d094c04c6da 100644 --- a/tokio-util/src/udp/frame.rs +++ b/tokio-util/src/udp/frame.rs @@ -81,17 +81,21 @@ where } // We're out of data. Try and fetch more data to decode - let addr = unsafe { - // Convert `&mut [MaybeUnit]` to `&mut [u8]` because we will be - // writing to it via `poll_recv_from` and therefore initializing the memory. - let buf = &mut *(pin.rd.chunk_mut() as *mut _ as *mut [MaybeUninit]); + let addr = { + // Safety: `chunk_mut()` returns a `&mut UninitSlice`, and `UninitSlice` is a + // transparent wrapper around `[MaybeUninit]`. + let buf = unsafe { &mut *(pin.rd.chunk_mut() as *mut _ as *mut [MaybeUninit]) }; let mut read = ReadBuf::uninit(buf); let ptr = read.filled().as_ptr(); let res = ready!(pin.socket.borrow().poll_recv_from(cx, &mut read)); assert_eq!(ptr, read.filled().as_ptr()); let addr = res?; - pin.rd.advance_mut(read.filled().len()); + + // Safety: This is guaranteed to be the number of initialized (and read) bytes due + // to the invariants provided by `ReadBuf::filled`. + unsafe { pin.rd.advance_mut(read.filled().len()) }; + addr };