@@ -10,6 +10,7 @@ use std::fmt;
1010use std:: io:: { self , Read , Write } ;
1111#[ cfg( not( target_os = "redox" ) ) ]
1212use std:: io:: { IoSlice , IoSliceMut } ;
13+ use std:: mem:: MaybeUninit ;
1314use std:: net:: { self , Ipv4Addr , Ipv6Addr , Shutdown } ;
1415#[ cfg( unix) ]
1516use std:: os:: unix:: io:: { FromRawFd , IntoRawFd } ;
@@ -286,7 +287,20 @@ impl Socket {
286287 /// This method might fail if the socket is not connected.
287288 ///
288289 /// [`connect`]: Socket::connect
289- pub fn recv ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
290+ ///
291+ /// # Safety
292+ ///
293+ /// Normally casting a `&mut [u8]` to `&mut [MaybeUninit<u8>]` would be
294+ /// unsound, as that allows us to write uninitialised bytes to the buffer.
295+ /// However this implementation promises to not write uninitialised bytes to
296+ /// the `buf`fer and passes it directly to `recv(2)` system call. This
297+ /// promise ensures that this function can be called using a `buf`fer of
298+ /// type `&mut [u8]`.
299+ ///
300+ /// Note that the [`io::Read::read`] implementation calls this function with
301+ /// a `buf`fer of type `&mut [u8]`, allowing initialised buffers to be used
302+ /// without using `unsafe`.
303+ pub fn recv ( & self , buf : & mut [ MaybeUninit < u8 > ] ) -> io:: Result < usize > {
290304 self . recv_with_flags ( buf, 0 )
291305 }
292306
@@ -297,15 +311,19 @@ impl Socket {
297311 ///
298312 /// [`recv`]: Socket::recv
299313 /// [`out_of_band_inline`]: Socket::out_of_band_inline
300- pub fn recv_out_of_band ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
314+ pub fn recv_out_of_band ( & self , buf : & mut [ MaybeUninit < u8 > ] ) -> io:: Result < usize > {
301315 self . recv_with_flags ( buf, sys:: MSG_OOB )
302316 }
303317
304318 /// Identical to [`recv`] but allows for specification of arbitrary flags to
305319 /// the underlying `recv` call.
306320 ///
307321 /// [`recv`]: Socket::recv
308- pub fn recv_with_flags ( & self , buf : & mut [ u8 ] , flags : sys:: c_int ) -> io:: Result < usize > {
322+ pub fn recv_with_flags (
323+ & self ,
324+ buf : & mut [ MaybeUninit < u8 > ] ,
325+ flags : sys:: c_int ,
326+ ) -> io:: Result < usize > {
309327 sys:: recv ( self . inner , buf, flags)
310328 }
311329
@@ -345,13 +363,27 @@ impl Socket {
345363 ///
346364 /// Successive calls return the same data. This is accomplished by passing
347365 /// `MSG_PEEK` as a flag to the underlying `recv` system call.
348- pub fn peek ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
366+ ///
367+ /// # Safety
368+ ///
369+ /// `peek` makes the same safety guarantees regarding the `buf`fer as
370+ /// [`recv`].
371+ ///
372+ /// [`recv`]: Socket::recv
373+ pub fn peek ( & self , buf : & mut [ MaybeUninit < u8 > ] ) -> io:: Result < usize > {
349374 self . recv_with_flags ( buf, sys:: MSG_PEEK )
350375 }
351376
352377 /// Receives data from the socket. On success, returns the number of bytes
353378 /// read and the address from whence the data came.
354- pub fn recv_from ( & self , buf : & mut [ u8 ] ) -> io:: Result < ( usize , SockAddr ) > {
379+ ///
380+ /// # Safety
381+ ///
382+ /// `recv_from` makes the same safety guarantees regarding the `buf`fer as
383+ /// [`recv`].
384+ ///
385+ /// [`recv`]: Socket::recv
386+ pub fn recv_from ( & self , buf : & mut [ MaybeUninit < u8 > ] ) -> io:: Result < ( usize , SockAddr ) > {
355387 self . recv_from_with_flags ( buf, 0 )
356388 }
357389
@@ -361,7 +393,7 @@ impl Socket {
361393 /// [`recv_from`]: Socket::recv_from
362394 pub fn recv_from_with_flags (
363395 & self ,
364- buf : & mut [ u8 ] ,
396+ buf : & mut [ MaybeUninit < u8 > ] ,
365397 flags : i32 ,
366398 ) -> io:: Result < ( usize , SockAddr ) > {
367399 sys:: recv_from ( self . inner , buf, flags)
@@ -400,7 +432,14 @@ impl Socket {
400432 ///
401433 /// On success, returns the number of bytes peeked and the address from
402434 /// whence the data came.
403- pub fn peek_from ( & self , buf : & mut [ u8 ] ) -> io:: Result < ( usize , SockAddr ) > {
435+ ///
436+ /// # Safety
437+ ///
438+ /// `peek_from` makes the same safety guarantees regarding the `buf`fer as
439+ /// [`recv`].
440+ ///
441+ /// [`recv`]: Socket::recv
442+ pub fn peek_from ( & self , buf : & mut [ MaybeUninit < u8 > ] ) -> io:: Result < ( usize , SockAddr ) > {
404443 self . recv_from_with_flags ( buf, sys:: MSG_PEEK )
405444 }
406445
@@ -1245,6 +1284,9 @@ impl Socket {
12451284
12461285impl Read for Socket {
12471286 fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
1287+ // Safety: the `recv` implementation promises not to write uninitialised
1288+ // bytes to the `buf`fer, so this casting is safe.
1289+ let buf = unsafe { & mut * ( buf as * mut [ u8 ] as * mut [ MaybeUninit < u8 > ] ) } ;
12481290 self . recv ( buf)
12491291 }
12501292
@@ -1256,6 +1298,8 @@ impl Read for Socket {
12561298
12571299impl < ' a > Read for & ' a Socket {
12581300 fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
1301+ // Safety: see other `Read::read` impl.
1302+ let buf = unsafe { & mut * ( buf as * mut [ u8 ] as * mut [ MaybeUninit < u8 > ] ) } ;
12591303 self . recv ( buf)
12601304 }
12611305
0 commit comments