@@ -21,7 +21,7 @@ use std::time::Duration;
2121use crate :: sys:: { self , c_int, getsockopt, setsockopt, Bool } ;
2222#[ cfg( not( target_os = "redox" ) ) ]
2323use crate :: RecvFlags ;
24- use crate :: { Domain , Protocol , SockAddr , TcpKeepalive , Type } ;
24+ use crate :: { Domain , MaybeUninitSlice , Protocol , SockAddr , TcpKeepalive , Type } ;
2525
2626/// Owned wrapper around a system socket.
2727///
@@ -339,19 +339,42 @@ impl Socket {
339339 ///
340340 /// [`recv`]: Socket::recv
341341 /// [`connect`]: Socket::connect
342+ ///
343+ /// # Safety
344+ ///
345+ /// Normally casting a `IoSliceMut` to `MaybeUninitSlice` would be unsound,
346+ /// as that allows us to write uninitialised bytes to the buffer. However
347+ /// this implementation promises to not write uninitialised bytes to the
348+ /// `bufs` and passes it directly to `recvmsg(2)` system call. This promise
349+ /// ensures that this function can be called using `bufs` of type `&mut
350+ /// [IoSliceMut]`.
351+ ///
352+ /// Note that the [`io::Read::read_vectored`] implementation calls this
353+ /// function with `buf`s of type `&mut [IoSliceMut]`, allowing initialised
354+ /// buffers to be used without using `unsafe`.
342355 #[ cfg( not( target_os = "redox" ) ) ]
343- pub fn recv_vectored ( & self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < ( usize , RecvFlags ) > {
356+ pub fn recv_vectored (
357+ & self ,
358+ bufs : & mut [ MaybeUninitSlice < ' _ > ] ,
359+ ) -> io:: Result < ( usize , RecvFlags ) > {
344360 self . recv_vectored_with_flags ( bufs, 0 )
345361 }
346362
347363 /// Identical to [`recv_vectored`] but allows for specification of arbitrary
348364 /// flags to the underlying `recvmsg`/`WSARecv` call.
349365 ///
350366 /// [`recv_vectored`]: Socket::recv_vectored
367+ ///
368+ /// # Safety
369+ ///
370+ /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
371+ /// as [`recv_vectored`].
372+ ///
373+ /// [`recv_vectored`]: Socket::recv_vectored
351374 #[ cfg( not( target_os = "redox" ) ) ]
352375 pub fn recv_vectored_with_flags (
353376 & self ,
354- bufs : & mut [ IoSliceMut < ' _ > ] ,
377+ bufs : & mut [ MaybeUninitSlice < ' _ > ] ,
355378 flags : i32 ,
356379 ) -> io:: Result < ( usize , RecvFlags ) > {
357380 sys:: recv_vectored ( self . inner , bufs, flags)
@@ -404,10 +427,17 @@ impl Socket {
404427 /// [`recv_from`] this allows passing multiple buffers.
405428 ///
406429 /// [`recv_from`]: Socket::recv_from
430+ ///
431+ /// # Safety
432+ ///
433+ /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
434+ /// as [`recv_vectored`].
435+ ///
436+ /// [`recv_vectored`]: Socket::recv_vectored
407437 #[ cfg( not( target_os = "redox" ) ) ]
408438 pub fn recv_from_vectored (
409439 & self ,
410- bufs : & mut [ IoSliceMut < ' _ > ] ,
440+ bufs : & mut [ MaybeUninitSlice < ' _ > ] ,
411441 ) -> io:: Result < ( usize , RecvFlags , SockAddr ) > {
412442 self . recv_from_vectored_with_flags ( bufs, 0 )
413443 }
@@ -416,10 +446,17 @@ impl Socket {
416446 /// arbitrary flags to the underlying `recvmsg`/`WSARecvFrom` call.
417447 ///
418448 /// [`recv_from_vectored`]: Socket::recv_from_vectored
449+ ///
450+ /// # Safety
451+ ///
452+ /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
453+ /// as [`recv_vectored`].
454+ ///
455+ /// [`recv_vectored`]: Socket::recv_vectored
419456 #[ cfg( not( target_os = "redox" ) ) ]
420457 pub fn recv_from_vectored_with_flags (
421458 & self ,
422- bufs : & mut [ IoSliceMut < ' _ > ] ,
459+ bufs : & mut [ MaybeUninitSlice < ' _ > ] ,
423460 flags : i32 ,
424461 ) -> io:: Result < ( usize , RecvFlags , SockAddr ) > {
425462 sys:: recv_from_vectored ( self . inner , bufs, flags)
@@ -1292,6 +1329,11 @@ impl Read for Socket {
12921329
12931330 #[ cfg( not( target_os = "redox" ) ) ]
12941331 fn read_vectored ( & mut self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
1332+ // Safety: both `IoSliceMut` and `MaybeUninitSlice` promise to have the
1333+ // same layout, that of `iovec`/`WSABUF`. Furthermore `recv_vectored`
1334+ // promises to not write unitialised bytes to the `bufs` and pass it
1335+ // directly to the `recvmsg` system call, so this is safe.
1336+ let bufs = unsafe { & mut * ( bufs as * mut [ IoSliceMut < ' _ > ] as * mut [ MaybeUninitSlice < ' _ > ] ) } ;
12951337 self . recv_vectored ( bufs) . map ( |( n, _) | n)
12961338 }
12971339}
@@ -1305,6 +1347,8 @@ impl<'a> Read for &'a Socket {
13051347
13061348 #[ cfg( not( target_os = "redox" ) ) ]
13071349 fn read_vectored ( & mut self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
1350+ // Safety: see other `Read::read` impl.
1351+ let bufs = unsafe { & mut * ( bufs as * mut [ IoSliceMut < ' _ > ] as * mut [ MaybeUninitSlice < ' _ > ] ) } ;
13081352 self . recv_vectored ( bufs) . map ( |( n, _) | n)
13091353 }
13101354}
0 commit comments