Skip to content

Commit e64152a

Browse files
io: fix unsound Buf::ensure_capacity_for
1 parent 4ca13e6 commit e64152a

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

tokio/src/io/blocking.rs

+16
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub(crate) struct Blocking<T> {
2121
pub(crate) struct Buf {
2222
buf: Vec<u8>,
2323
pos: usize,
24+
init_len: usize,
2425
}
2526

2627
pub(crate) const DEFAULT_MAX_BUF_SIZE: usize = 2 * 1024 * 1024;
@@ -190,6 +191,7 @@ impl Buf {
190191
Buf {
191192
buf: Vec::with_capacity(n),
192193
pos: 0,
194+
init_len: 0,
193195
}
194196
}
195197

@@ -220,6 +222,7 @@ impl Buf {
220222
let n = cmp::min(src.len(), max_buf_size);
221223

222224
self.buf.extend_from_slice(&src[..n]);
225+
self.init_len = cmp::max(self.init_len, self.buf.len());
223226
n
224227
}
225228

@@ -236,6 +239,18 @@ impl Buf {
236239
self.buf.reserve(len - self.buf.len());
237240
}
238241

242+
if self.init_len < len {
243+
debug_assert!(self.init_len < self.buf.capacity(), "init_len of Vec is bigger than the capacity");
244+
debug_assert!(len <= self.buf.capacity(), "uninit area of Vec is bigger than the capacity");
245+
246+
let uninit_len = len - self.init_len;
247+
// SAFETY: the area is within the allocation of the Vec
248+
unsafe {
249+
self.buf.as_mut_ptr().add(self.init_len).write_bytes(0, uninit_len);
250+
}
251+
}
252+
253+
// SAFETY: `len` is within the capacity and is init
239254
unsafe {
240255
self.buf.set_len(len);
241256
}
@@ -287,6 +302,7 @@ cfg_fs! {
287302
self.buf.extend_from_slice(&buf[..len]);
288303
rem -= len;
289304
}
305+
self.init_len = cmp::max(self.init_len, self.buf.len());
290306

291307
max_buf_size - rem
292308
}

0 commit comments

Comments
 (0)