Skip to content

Commit 3f3ea99

Browse files
zh-jqcursoragent
andcommitted
Avoid zeroing I/O buffers that are filled before read
Allocate recv/copy buffers with uninitialized capacity instead of vec![0]/BytesMut::zeroed, since only the filled prefix is ever observed. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent ea6595c commit 3f3ea99

18 files changed

Lines changed: 66 additions & 28 deletions

File tree

lib/vey-cert-agent/src/query.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ impl QueryRuntime {
3939
QueryRuntime {
4040
socket,
4141
query_handle,
42-
read_buffer: vec![0u8; 16384].into_boxed_slice(),
42+
// SAFETY: only `read_buffer[..len]` is parsed after poll_recv fills it.
43+
read_buffer: unsafe { Box::<[u8]>::new_uninit_slice(16384).assume_init() },
4344
write_queue: VecDeque::new(),
4445
protective_ttl: config.protective_cache_ttl,
4546
maximum_ttl: config.maximum_cache_ttl,

lib/vey-daemon/src/listen/udp/listen.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,13 @@ where
494494
ingress_net_filter: None,
495495
_alive_guard: None,
496496

497-
packet_buf: vec![0; self.packet_max_size as usize],
497+
// SAFETY: only `packet_buf[..nr]` is copied after recv fills it.
498+
packet_buf: {
499+
let n = self.packet_max_size as usize;
500+
let mut v = Vec::with_capacity(n);
501+
unsafe { v.set_len(n) };
502+
v
503+
},
498504
}
499505
}
500506

@@ -518,7 +524,11 @@ where
518524

519525
let mut packets_buf = Vec::with_capacity(self.conn_track.batch_recv_size());
520526
for _i in 0..self.conn_track.batch_recv_size() {
521-
packets_buf.push(vec![0; self.packet_max_size as usize]);
527+
// SAFETY: only `packets_buf[i][..nr]` is copied after recv fills it.
528+
let n = self.packet_max_size as usize;
529+
let mut v = Vec::with_capacity(n);
530+
unsafe { v.set_len(n) };
531+
packets_buf.push(v);
522532
}
523533

524534
ListenUdpRuntimeInstance {

lib/vey-h2/src/body/encoder.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ impl H2BodyEncodeTransferInternal {
107107
}
108108
}
109109
} else {
110-
let mut data = BytesMut::zeroed(self.buffer_size);
110+
let mut data = BytesMut::with_capacity(self.buffer_size);
111+
// SAFETY: only `filled()` / `split_to(nr)` is used after poll_read.
112+
unsafe { data.set_len(self.buffer_size) };
111113
let mut buf = ReadBuf::new(&mut data);
112114
ready!(reader.as_mut().poll_read(cx, &mut buf))
113115
.map_err(H2StreamBodyEncodeTransferError::ReadError)?;

lib/vey-hickory-client/src/io/quic.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ async fn quic_recv(mut recv_stream: RecvStream) -> Result<DnsResponse, NetError>
144144
.map_err(|e| format!("quic read len error: {e}"))?;
145145
let message_len = u16::from_be_bytes(len_buf) as usize;
146146

147-
let mut buffer = vec![0u8; message_len];
147+
// SAFETY: `read_exact` fully initializes `buffer` before it is parsed.
148+
let mut buffer = Vec::with_capacity(message_len);
149+
unsafe { buffer.set_len(message_len) };
148150
recv_stream
149151
.read_exact(&mut buffer)
150152
.await

lib/vey-hickory-client/src/io/udp.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,12 @@ async fn udp_send_recv(
104104
}
105105

106106
loop {
107-
let mut recv_buf = vec![0; MAX_RECEIVE_BUFFER_SIZE];
107+
// SAFETY: only `[..nr]` is kept after recv fills it.
108+
let mut recv_buf = Vec::with_capacity(MAX_RECEIVE_BUFFER_SIZE);
109+
unsafe { recv_buf.set_len(MAX_RECEIVE_BUFFER_SIZE) };
108110

109111
let nr = socket.recv(&mut recv_buf).await?;
110-
recv_buf.resize(nr, 0);
112+
recv_buf.truncate(nr);
111113
let response = DnsResponse::from_buffer(recv_buf)?;
112114
if response.id() != id {
113115
continue;

lib/vey-io-ext/src/stream/copy.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ impl StreamCopyBuffer {
7676
fn new(config: &StreamCopyConfig) -> Self {
7777
StreamCopyBuffer {
7878
read_done: false,
79-
buf: vec![0; config.buffer_size].into_boxed_slice(),
79+
// SAFETY: only `buf[w_off..r_off]` is read after poll_read fills it.
80+
buf: unsafe { Box::<[u8]>::new_uninit_slice(config.buffer_size).assume_init() },
8081
yield_size: config.yield_size,
8182
r_off: 0,
8283
w_off: 0,
@@ -89,11 +90,12 @@ impl StreamCopyBuffer {
8990

9091
fn with_data(config: &StreamCopyConfig, mut buf: Vec<u8>) -> Self {
9192
let r_off = buf.len();
92-
if buf.capacity() < config.buffer_size {
93-
buf.resize(config.buffer_size, 0);
94-
} else {
95-
buf.resize(buf.capacity(), 0);
93+
let new_len = config.buffer_size.max(buf.capacity());
94+
if buf.capacity() < new_len {
95+
buf.reserve_exact(new_len - buf.capacity());
9696
}
97+
// SAFETY: only `[0..r_off]` is readable until subsequent reads fill more.
98+
unsafe { buf.set_len(new_len) };
9799
StreamCopyBuffer {
98100
read_done: false,
99101
buf: buf.into_boxed_slice(),

lib/vey-io-ext/src/stream/line_recv_vec.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,17 @@ impl LineRecvVec {
2222
length: 0,
2323
line_start: 0,
2424
line_end: 0,
25-
buf: vec![0; cap].into_boxed_slice(),
25+
// SAFETY: only `buf[line_start..line_end]` / `[0..length]` are read after fills.
26+
buf: unsafe { Box::<[u8]>::new_uninit_slice(cap).assume_init() },
2627
}
2728
}
2829

2930
pub fn with_data(data: &[u8], cap: usize) -> Self {
30-
let mut buf = Vec::with_capacity(cap);
31+
let mut buf = Vec::with_capacity(cap.max(data.len()));
3132
buf.extend_from_slice(data);
3233
if cap > data.len() {
33-
buf.resize(cap, 0);
34+
// SAFETY: only `[0..length]` is readable until subsequent reads fill more.
35+
unsafe { buf.set_len(cap) };
3436
}
3537
LineRecvVec {
3638
length: data.len(),

lib/vey-io-ext/src/udp/relay/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ impl UdpRelayPacket {
3232
fn new(reserved_size: usize, packet_size: u16) -> Self {
3333
let buf_size = packet_size as usize + reserved_size;
3434
UdpRelayPacket {
35-
buf: vec![0; buf_size].into_boxed_slice(),
35+
// SAFETY: only `buf[off..end]` is read after recv fills that range.
36+
buf: unsafe { Box::<[u8]>::new_uninit_slice(buf_size).assume_init() },
3637
buf_data_off: 0,
3738
buf_data_end: 0,
3839
ups: UpstreamAddr::empty(),

lib/vey-io-ext/src/udp/stream_copy/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ pub struct UdpCopyPacket {
3737
impl UdpCopyPacket {
3838
pub(crate) fn new(reserved_size: usize, packet_size: u16) -> Self {
3939
let buf_size = packet_size as usize + reserved_size;
40+
let mut buf = BytesMut::with_capacity(buf_size);
41+
// SAFETY: only `buf[off..end]` is read after recv fills that range.
42+
unsafe { buf.set_len(buf_size) };
4043
UdpCopyPacket {
41-
buf: BytesMut::zeroed(buf_size),
44+
buf,
4245
buf_data_off: 0,
4346
buf_data_end: 0,
4447
}

lib/vey-ip-locate/src/query.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ impl IpLocationQueryRuntime {
3838
IpLocationQueryRuntime {
3939
socket,
4040
query_handle,
41-
read_buffer: vec![0u8; 16384].into_boxed_slice(),
41+
// SAFETY: only `read_buffer[..len]` is parsed after poll_recv fills it.
42+
read_buffer: unsafe { Box::<[u8]>::new_uninit_slice(16384).assume_init() },
4243
write_queue: VecDeque::new(),
4344
default_expire_ttl: config.default_expire_ttl,
4445
maximum_expire_ttl: config.maximum_expire_ttl,

0 commit comments

Comments
 (0)