For absolutely no reason I was reading the tcp(7) manpage, and it turns out tcp sockets support the MSG_TRUNC flag, which makes the kernel discard any received data instead of writing it, while still returning the number of bytes received. recv() assumes that the kernel writes min(buffer len, recv return value) bytes, so you can pass an uninit array and get a mut slice of MaybeUninit::uninit().assume_init() u8 (probably not too bad, as the syscall should prevent the compiler from making any assumptions, but it's still technically ub).
https://man7.org/linux/man-pages/man7/tcp.7.html
Since Linux 2.4, Linux supports the use of MSG_TRUNC in the flags argument of recv(2) (and recvmsg(2)). This flag causes the received bytes of data to be discarded, rather than passed back in a caller-supplied buffer. Since Linux 2.4.4, MSG_TRUNC also has this effect when used in conjunction with MSG_OOB to receive out-of-band data.
use std::{
io::Write,
mem::MaybeUninit,
net::{TcpListener, TcpStream},
thread,
time::Duration,
};
use rustix::{self, net::RecvFlags};
fn main() -> eyre::Result<()> {
thread::spawn(|| -> eyre::Result<()> {
let l = TcpListener::bind("127.0.0.1:1234")?;
let mut c = l.accept()?.0;
c.write_all(&[0; 128])?;
Ok(())
});
thread::sleep(Duration::from_millis(100));
let s = TcpStream::connect("127.0.0.1:1234")?;
let mut stack = [MaybeUninit::uninit(); 128];
let stack = rustix::net::recv(s, &mut stack, RecvFlags::TRUNC)?.0.0;
println!("{stack:?}");
assert!(stack != [0; 128] && stack.len() == 128);
Ok(())
}
(rustix::net is configured out on the playground)
For absolutely no reason I was reading the
tcp(7)manpage, and it turns out tcp sockets support theMSG_TRUNCflag, which makes the kernel discard any received data instead of writing it, while still returning the number of bytes received. recv() assumes that the kernel writes min(buffer len, recv return value) bytes, so you can pass an uninit array and get a mut slice of MaybeUninit::uninit().assume_init() u8 (probably not too bad, as the syscall should prevent the compiler from making any assumptions, but it's still technically ub).https://man7.org/linux/man-pages/man7/tcp.7.html
(rustix::net is configured out on the playground)