From f0bf96cef8f135502f6f846b156761cae8380953 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Mon, 4 Jan 2021 12:41:47 +0200 Subject: [PATCH] io: guard against integer overflow in BufWriter In the implementation of AsyncWrite::poll_write_vectored for BufWriter, the total length of the data can technically overflow usize even with safely obtained buffer slices, since slices may overlap. --- tokio/src/io/util/buf_writer.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tokio/src/io/util/buf_writer.rs b/tokio/src/io/util/buf_writer.rs index 0f71c0b98b4..0607e4151c2 100644 --- a/tokio/src/io/util/buf_writer.rs +++ b/tokio/src/io/util/buf_writer.rs @@ -136,15 +136,19 @@ impl AsyncWrite for BufWriter { cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll> { - if self.as_mut().project().inner.is_write_vectored() { - let total_len = bufs.iter().map(|b| b.len()).sum::(); - if self.buf.len() + total_len > self.buf.capacity() { + if self.inner.is_write_vectored() { + let total_len = bufs + .iter() + .fold(0usize, |acc, b| acc.saturating_add(b.len())); + if total_len > self.buf.capacity() - self.buf.len() { ready!(self.as_mut().flush_buf(cx))?; } let me = self.as_mut().project(); if total_len >= me.buf.capacity() { // It's more efficient to pass the slices directly to the // underlying writer than to buffer them. + // The case when the total_len calculation saturates at + // usize::MAX is also handled here. me.inner.poll_write_vectored(cx, bufs) } else { bufs.iter().for_each(|b| me.buf.extend_from_slice(b));