diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2020-07-27 19:31:53 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-27 19:31:53 +0900 |
| commit | 1361b02c9fc9a96ab4baf82994a0f1b29beff41a (patch) | |
| tree | eed3fc7fa7f630874736473322c393e0f0961e44 | |
| parent | 1841fb97e17f5e41c609cd11ab114c7ac1f3de2a (diff) | |
| parent | 7a5d3abfb1aa3a38e0b3b3508c760fc8e712226c (diff) | |
| download | rust-1361b02c9fc9a96ab4baf82994a0f1b29beff41a.tar.gz rust-1361b02c9fc9a96ab4baf82994a0f1b29beff41a.zip | |
Rollup merge of #74088 - tmiasko:write-all-vectored-empty, r=KodrAus
Avoid writes without any data in `Write::write_all_vectored` Previously, when non-empty sequence of empty IoSlices have been provided to `Write::write_all_vectored`, the buffers would be written as is with `Write::write_vectored` and subsequently the return value `Ok(0)` would be misinterpreted as an error. Avoid writes without any data by advancing the buffers first. This matches the documented behaviour of `Write::write_all_vectored` and is analogous to what happens in `Write::write_all`.
| -rw-r--r-- | src/libstd/io/mod.rs | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 797318d95b7..9eb54c2cc00 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -251,7 +251,6 @@ use crate::cmp; use crate::fmt; -use crate::mem; use crate::memchr; use crate::ops::{Deref, DerefMut}; use crate::ptr; @@ -1435,12 +1434,15 @@ pub trait Write { /// ``` #[unstable(feature = "write_all_vectored", issue = "70436")] fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> { + // Guarantee that bufs is empty if it contains no data, + // to avoid calling write_vectored if there is no data to be written. + bufs = IoSlice::advance(bufs, 0); while !bufs.is_empty() { match self.write_vectored(bufs) { Ok(0) => { return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")); } - Ok(n) => bufs = IoSlice::advance(mem::take(&mut bufs), n), + Ok(n) => bufs = IoSlice::advance(bufs, n), Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } @@ -2958,6 +2960,7 @@ mod tests { #[rustfmt::skip] // Becomes unreadable otherwise. let tests: Vec<(_, &'static [u8])> = vec![ (vec![], &[]), + (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]), (vec![IoSlice::new(&[1])], &[1]), (vec![IoSlice::new(&[1, 2])], &[1, 2]), (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]), |
