Skip to content

Commit 3b0e286

Browse files
Add uninit buffer ancillary APIs (#1108)
* Add uninit buffer ancillary APIs Signed-off-by: Alex Saveau <[email protected]> * Make the `new` functions use `MaybeUninit`. * Add a CHANGES.md entry for the change. --------- Signed-off-by: Alex Saveau <[email protected]> Co-authored-by: Dan Gohman <[email protected]>
1 parent 28d76e2 commit 3b0e286

File tree

4 files changed

+77
-51
lines changed

4 files changed

+77
-51
lines changed

CHANGES.md

+6
Original file line numberDiff line numberDiff line change
@@ -267,5 +267,11 @@ argument optionallly containing a raw file descriptor.
267267

268268
[`rustix::io_uring::io_uring_setup`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/fn.io_uring_setup.html
269269

270+
The buffer for [`SendAncillaryBuffer`] and [`RecvAncillaryBuffer`] is now
271+
a `[MaybeUninit<u8>]` instead of a `[u8]`.
272+
273+
[`SendAncillaryBuffer`]: https://docs.rs/rustix/1.0.0/rustix/net/struct.SendAncillaryBuffer.html
274+
[`RecvAncillaryBuffer`]: https://docs.rs/rustix/1.0.0/rustix/net/struct.RecvAncillaryBuffer.html
275+
270276
All explicitly deprecated functions and types have been removed. Their
271277
deprecation messages will have identified alternatives.

src/net/send_recv/msg.rs

+42-25
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::net::UCred;
1414
use core::fmt;
1515
use core::iter::FusedIterator;
1616
use core::marker::PhantomData;
17-
use core::mem::{align_of, size_of, size_of_val, take};
17+
use core::mem::{align_of, size_of, size_of_val, take, MaybeUninit};
1818
#[cfg(linux_kernel)]
1919
use core::ptr::addr_of;
2020
use core::{ptr, slice};
@@ -28,25 +28,31 @@ use super::{RecvFlags, ReturnFlags, SendFlags, SocketAddrAny};
2828
///
2929
/// Allocate a buffer for a single file descriptor:
3030
/// ```
31+
/// # use core::mem::MaybeUninit;
3132
/// # use rustix::cmsg_space;
32-
/// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
33+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(1))];
34+
/// # let _: &[MaybeUninit<u8>] = space.as_slice();
3335
/// ```
3436
///
3537
/// Allocate a buffer for credentials:
3638
/// ```
3739
/// # #[cfg(linux_kernel)]
3840
/// # {
41+
/// # use core::mem::MaybeUninit;
3942
/// # use rustix::cmsg_space;
40-
/// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
43+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmCredentials(1))];
44+
/// # let _: &[MaybeUninit<u8>] = space.as_slice();
4145
/// # }
4246
/// ```
4347
///
4448
/// Allocate a buffer for two file descriptors and credentials:
4549
/// ```
4650
/// # #[cfg(linux_kernel)]
4751
/// # {
52+
/// # use core::mem::MaybeUninit;
4853
/// # use rustix::cmsg_space;
49-
/// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
54+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
55+
/// # let _: &[MaybeUninit<u8>] = space.as_slice();
5056
/// # }
5157
/// ```
5258
#[macro_export]
@@ -169,7 +175,7 @@ pub enum RecvAncillaryMessage<'a> {
169175
/// [`push`]: SendAncillaryBuffer::push
170176
pub struct SendAncillaryBuffer<'buf, 'slice, 'fd> {
171177
/// Raw byte buffer for messages.
172-
buffer: &'buf mut [u8],
178+
buffer: &'buf mut [MaybeUninit<u8>],
173179

174180
/// The amount of the buffer that is used.
175181
length: usize,
@@ -178,8 +184,8 @@ pub struct SendAncillaryBuffer<'buf, 'slice, 'fd> {
178184
_phantom: PhantomData<&'slice [BorrowedFd<'fd>]>,
179185
}
180186

181-
impl<'buf> From<&'buf mut [u8]> for SendAncillaryBuffer<'buf, '_, '_> {
182-
fn from(buffer: &'buf mut [u8]) -> Self {
187+
impl<'buf> From<&'buf mut [MaybeUninit<u8>]> for SendAncillaryBuffer<'buf, '_, '_> {
188+
fn from(buffer: &'buf mut [MaybeUninit<u8>]) -> Self {
183189
Self::new(buffer)
184190
}
185191
}
@@ -205,19 +211,21 @@ impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> {
205211
///
206212
/// Allocate a buffer for a single file descriptor:
207213
/// ```
214+
/// # use core::mem::MaybeUninit;
208215
/// # use rustix::cmsg_space;
209216
/// # use rustix::net::SendAncillaryBuffer;
210-
/// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
217+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(1))];
211218
/// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
212219
/// ```
213220
///
214221
/// Allocate a buffer for credentials:
215222
/// ```
216223
/// # #[cfg(linux_kernel)]
217224
/// # {
225+
/// # use core::mem::MaybeUninit;
218226
/// # use rustix::cmsg_space;
219227
/// # use rustix::net::SendAncillaryBuffer;
220-
/// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
228+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmCredentials(1))];
221229
/// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
222230
/// # }
223231
/// ```
@@ -226,16 +234,17 @@ impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> {
226234
/// ```
227235
/// # #[cfg(linux_kernel)]
228236
/// # {
237+
/// # use core::mem::MaybeUninit;
229238
/// # use rustix::cmsg_space;
230239
/// # use rustix::net::SendAncillaryBuffer;
231-
/// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
240+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
232241
/// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
233242
/// # }
234243
/// ```
235244
///
236245
/// [`send`]: crate::net::send
237246
#[inline]
238-
pub fn new(buffer: &'buf mut [u8]) -> Self {
247+
pub fn new(buffer: &'buf mut [MaybeUninit<u8>]) -> Self {
239248
Self {
240249
buffer: align_for_cmsghdr(buffer),
241250
length: 0,
@@ -253,7 +262,7 @@ impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> {
253262
return core::ptr::null_mut();
254263
}
255264

256-
self.buffer.as_mut_ptr()
265+
self.buffer.as_mut_ptr().cast()
257266
}
258267

259268
/// Returns the length of the message data.
@@ -306,7 +315,7 @@ impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> {
306315
let buffer = leap!(self.buffer.get_mut(..new_length));
307316

308317
// Fill the new part of the buffer with zeroes.
309-
buffer[self.length..new_length].fill(0);
318+
buffer[self.length..new_length].fill(MaybeUninit::new(0));
310319
self.length = new_length;
311320

312321
// Get the last header in the buffer.
@@ -344,7 +353,7 @@ impl<'slice, 'fd> Extend<SendAncillaryMessage<'slice, 'fd>>
344353
#[derive(Default)]
345354
pub struct RecvAncillaryBuffer<'buf> {
346355
/// Raw byte buffer for messages.
347-
buffer: &'buf mut [u8],
356+
buffer: &'buf mut [MaybeUninit<u8>],
348357

349358
/// The portion of the buffer we've read from already.
350359
read: usize,
@@ -353,8 +362,8 @@ pub struct RecvAncillaryBuffer<'buf> {
353362
length: usize,
354363
}
355364

356-
impl<'buf> From<&'buf mut [u8]> for RecvAncillaryBuffer<'buf> {
357-
fn from(buffer: &'buf mut [u8]) -> Self {
365+
impl<'buf> From<&'buf mut [MaybeUninit<u8>]> for RecvAncillaryBuffer<'buf> {
366+
fn from(buffer: &'buf mut [MaybeUninit<u8>]) -> Self {
358367
Self::new(buffer)
359368
}
360369
}
@@ -370,19 +379,21 @@ impl<'buf> RecvAncillaryBuffer<'buf> {
370379
///
371380
/// Allocate a buffer for a single file descriptor:
372381
/// ```
382+
/// # use core::mem::MaybeUninit;
373383
/// # use rustix::cmsg_space;
374384
/// # use rustix::net::RecvAncillaryBuffer;
375-
/// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
385+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(1))];
376386
/// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
377387
/// ```
378388
///
379389
/// Allocate a buffer for credentials:
380390
/// ```
381391
/// # #[cfg(linux_kernel)]
382392
/// # {
393+
/// # use core::mem::MaybeUninit;
383394
/// # use rustix::cmsg_space;
384395
/// # use rustix::net::RecvAncillaryBuffer;
385-
/// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
396+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmCredentials(1))];
386397
/// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
387398
/// # }
388399
/// ```
@@ -391,16 +402,17 @@ impl<'buf> RecvAncillaryBuffer<'buf> {
391402
/// ```
392403
/// # #[cfg(linux_kernel)]
393404
/// # {
405+
/// # use core::mem::MaybeUninit;
394406
/// # use rustix::cmsg_space;
395407
/// # use rustix::net::RecvAncillaryBuffer;
396-
/// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
408+
/// let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
397409
/// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
398410
/// # }
399411
/// ```
400412
///
401413
/// [`recv`]: crate::net::recv
402414
#[inline]
403-
pub fn new(buffer: &'buf mut [u8]) -> Self {
415+
pub fn new(buffer: &'buf mut [MaybeUninit<u8>]) -> Self {
404416
Self {
405417
buffer: align_for_cmsghdr(buffer),
406418
read: 0,
@@ -418,7 +430,7 @@ impl<'buf> RecvAncillaryBuffer<'buf> {
418430
return core::ptr::null_mut();
419431
}
420432

421-
self.buffer.as_mut_ptr()
433+
self.buffer.as_mut_ptr().cast()
422434
}
423435

424436
/// Returns the length of the message data.
@@ -459,7 +471,7 @@ impl Drop for RecvAncillaryBuffer<'_> {
459471
/// Return a slice of `buffer` starting at the first `cmsghdr` alignment
460472
/// boundary.
461473
#[inline]
462-
fn align_for_cmsghdr(buffer: &mut [u8]) -> &mut [u8] {
474+
fn align_for_cmsghdr(buffer: &mut [MaybeUninit<u8>]) -> &mut [MaybeUninit<u8>] {
463475
// If the buffer is empty, we won't be writing anything into it, so it
464476
// doesn't need to be aligned.
465477
if buffer.is_empty() {
@@ -884,6 +896,7 @@ mod messages {
884896
use crate::backend::net::msghdr;
885897
use core::iter::FusedIterator;
886898
use core::marker::PhantomData;
899+
use core::mem::MaybeUninit;
887900
use core::ptr::NonNull;
888901

889902
/// An iterator over the messages in an ancillary buffer.
@@ -897,15 +910,19 @@ mod messages {
897910
header: Option<NonNull<c::cmsghdr>>,
898911

899912
/// Capture the original lifetime of the buffer.
900-
_buffer: PhantomData<&'buf mut [u8]>,
913+
_buffer: PhantomData<&'buf mut [MaybeUninit<u8>]>,
901914
}
902915

916+
pub(super) trait AllowedMsgBufType {}
917+
impl AllowedMsgBufType for u8 {}
918+
impl AllowedMsgBufType for MaybeUninit<u8> {}
919+
903920
impl<'buf> Messages<'buf> {
904921
/// Create a new iterator over messages from a byte buffer.
905-
pub(super) fn new(buf: &'buf mut [u8]) -> Self {
922+
pub(super) fn new(buf: &'buf mut [impl AllowedMsgBufType]) -> Self {
906923
let mut msghdr = msghdr::zero_msghdr();
907924
msghdr.msg_control = buf.as_mut_ptr().cast();
908-
msghdr.msg_controllen = buf.len().try_into().unwrap();
925+
msghdr.msg_controllen = buf.len().try_into().expect("buffer too large for msghdr");
909926

910927
// Get the first header.
911928
let header = NonNull::new(unsafe { c::CMSG_FIRSTHDR(&msghdr) });

tests/net/unix.rs

+16-14
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustix::net::{
1313
accept, bind, connect, listen, socket, AddressFamily, SocketAddrUnix, SocketType,
1414
};
1515
use rustix::path::DecInt;
16+
use std::mem::MaybeUninit;
1617
use std::path::Path;
1718
use std::str::FromStr as _;
1819
use std::sync::{Arc, Condvar, Mutex};
@@ -449,13 +450,13 @@ fn test_unix_msg_with_scm_rights() {
449450
let mut pipe_end = None;
450451

451452
let mut buffer = [0; BUFFER_SIZE];
452-
let mut cmsg_space = [0; rustix::cmsg_space!(ScmRights(1))];
453+
let mut cmsg_space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(1))];
453454

454455
'exit: loop {
455456
let data_socket = accept(&connection_socket).unwrap();
456457
let mut sum = 0;
457458
loop {
458-
let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut cmsg_space);
459+
let mut cmsg_buffer = RecvAncillaryBuffer::new(cmsg_space.as_mut_slice());
459460
let result = recvmsg(
460461
&data_socket,
461462
&mut [IoSliceMut::new(&mut buffer)],
@@ -560,8 +561,8 @@ fn test_unix_msg_with_scm_rights() {
560561
// Format the CMSG.
561562
let we = [write_end.as_fd()];
562563
let msg = SendAncillaryMessage::ScmRights(&we);
563-
let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
564-
let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
564+
let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(1))];
565+
let mut cmsg_buffer = SendAncillaryBuffer::new(space.as_mut_slice());
565566
assert!(cmsg_buffer.push(msg));
566567

567568
connect(&data_socket, &addr).unwrap();
@@ -620,8 +621,8 @@ fn test_unix_peercred_explicit() {
620621

621622
let ucred = sockopt::socket_peercred(&send_sock).unwrap();
622623
let msg = SendAncillaryMessage::ScmCredentials(ucred);
623-
let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
624-
let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
624+
let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmCredentials(1))];
625+
let mut cmsg_buffer = SendAncillaryBuffer::new(space.as_mut_slice());
625626
assert!(cmsg_buffer.push(msg));
626627

627628
sendmsg(
@@ -632,8 +633,8 @@ fn test_unix_peercred_explicit() {
632633
)
633634
.unwrap();
634635

635-
let mut cmsg_space = [0; rustix::cmsg_space!(ScmCredentials(1))];
636-
let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut cmsg_space);
636+
let mut cmsg_space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmCredentials(1))];
637+
let mut cmsg_buffer = RecvAncillaryBuffer::new(cmsg_space.as_mut_slice());
637638

638639
let mut buffer = [0; BUFFER_SIZE];
639640
let result = recvmsg(
@@ -692,8 +693,8 @@ fn test_unix_peercred_implicit() {
692693
)
693694
.unwrap();
694695

695-
let mut cmsg_space = [0; rustix::cmsg_space!(ScmCredentials(1))];
696-
let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut cmsg_space);
696+
let mut cmsg_space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmCredentials(1))];
697+
let mut cmsg_buffer = RecvAncillaryBuffer::new(cmsg_space.as_mut_slice());
697698

698699
let mut buffer = [0; BUFFER_SIZE];
699700
let result = recvmsg(
@@ -747,13 +748,14 @@ fn test_unix_msg_with_combo() {
747748
let mut yet_another_pipe_end = None;
748749

749750
let mut buffer = [0; BUFFER_SIZE];
750-
let mut cmsg_space = [0; rustix::cmsg_space!(ScmRights(2), ScmRights(1))];
751+
let mut cmsg_space =
752+
[MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(2), ScmRights(1))];
751753

752754
'exit: loop {
753755
let data_socket = accept(&connection_socket).unwrap();
754756
let mut sum = 0;
755757
loop {
756-
let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut cmsg_space);
758+
let mut cmsg_buffer = RecvAncillaryBuffer::new(cmsg_space.as_mut_slice());
757759
let result = recvmsg(
758760
&data_socket,
759761
&mut [IoSliceMut::new(&mut buffer)],
@@ -872,8 +874,8 @@ fn test_unix_msg_with_combo() {
872874

873875
let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap();
874876

875-
let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmRights(1))];
876-
let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
877+
let mut space = [MaybeUninit::uninit(); rustix::cmsg_space!(ScmRights(2), ScmRights(1))];
878+
let mut cmsg_buffer = SendAncillaryBuffer::new(space.as_mut_slice());
877879

878880
// Format a CMSG.
879881
let we = [write_end.as_fd(), another_write_end.as_fd()];

0 commit comments

Comments
 (0)