@@ -10,6 +10,7 @@ use std::fmt;
10
10
use std:: io:: { self , Read , Write } ;
11
11
#[ cfg( not( target_os = "redox" ) ) ]
12
12
use std:: io:: { IoSlice , IoSliceMut } ;
13
+ use std:: mem:: MaybeUninit ;
13
14
use std:: net:: { self , Ipv4Addr , Ipv6Addr , Shutdown } ;
14
15
#[ cfg( unix) ]
15
16
use std:: os:: unix:: io:: { FromRawFd , IntoRawFd } ;
@@ -286,7 +287,20 @@ impl Socket {
286
287
/// This method might fail if the socket is not connected.
287
288
///
288
289
/// [`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 > {
290
304
self . recv_with_flags ( buf, 0 )
291
305
}
292
306
@@ -297,15 +311,19 @@ impl Socket {
297
311
///
298
312
/// [`recv`]: Socket::recv
299
313
/// [`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 > {
301
315
self . recv_with_flags ( buf, sys:: MSG_OOB )
302
316
}
303
317
304
318
/// Identical to [`recv`] but allows for specification of arbitrary flags to
305
319
/// the underlying `recv` call.
306
320
///
307
321
/// [`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 > {
309
327
sys:: recv ( self . inner , buf, flags)
310
328
}
311
329
@@ -345,13 +363,27 @@ impl Socket {
345
363
///
346
364
/// Successive calls return the same data. This is accomplished by passing
347
365
/// `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 > {
349
374
self . recv_with_flags ( buf, sys:: MSG_PEEK )
350
375
}
351
376
352
377
/// Receives data from the socket. On success, returns the number of bytes
353
378
/// 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 ) > {
355
387
self . recv_from_with_flags ( buf, 0 )
356
388
}
357
389
@@ -361,7 +393,7 @@ impl Socket {
361
393
/// [`recv_from`]: Socket::recv_from
362
394
pub fn recv_from_with_flags (
363
395
& self ,
364
- buf : & mut [ u8 ] ,
396
+ buf : & mut [ MaybeUninit < u8 > ] ,
365
397
flags : i32 ,
366
398
) -> io:: Result < ( usize , SockAddr ) > {
367
399
sys:: recv_from ( self . inner , buf, flags)
@@ -400,7 +432,14 @@ impl Socket {
400
432
///
401
433
/// On success, returns the number of bytes peeked and the address from
402
434
/// 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 ) > {
404
443
self . recv_from_with_flags ( buf, sys:: MSG_PEEK )
405
444
}
406
445
@@ -1245,6 +1284,9 @@ impl Socket {
1245
1284
1246
1285
impl Read for Socket {
1247
1286
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 > ] ) } ;
1248
1290
self . recv ( buf)
1249
1291
}
1250
1292
@@ -1256,6 +1298,8 @@ impl Read for Socket {
1256
1298
1257
1299
impl < ' a > Read for & ' a Socket {
1258
1300
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 > ] ) } ;
1259
1303
self . recv ( buf)
1260
1304
}
1261
1305
0 commit comments