From 03753ba5a21fe0e4bfc34e9691d4b13f24c90af4 Mon Sep 17 00:00:00 2001 From: Steven Fackler <sfackler@gmail.com> Date: Sat, 21 Feb 2015 11:15:58 -0800 Subject: [PATCH] Fix io::Take behavior with limit 0 We can't call into the inner reader for a 0-byte read because that may end up blocking or returning an error. --- src/libstd/io/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c38d52161c9..5e810926ee4 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -669,6 +669,11 @@ impl<T> Take<T> { impl<T: Read> Read for Take<T> { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(0); + } + let max = cmp::min(buf.len() as u64, self.limit) as usize; let n = try!(self.inner.read(&mut buf[..max])); self.limit -= n as u64; @@ -846,6 +851,7 @@ impl<B: BufRead> Iterator for Lines<B> { mod tests { use prelude::v1::*; use io::prelude::*; + use io; use super::Cursor; #[test] @@ -943,4 +949,18 @@ mod tests { let mut v = String::new(); assert!(c.read_to_string(&mut v).is_err()); } + + #[test] + fn take_eof() { + struct R; + + impl Read for R { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + Err(io::Error::new(io::ErrorKind::Other, "", None)) + } + } + + let mut buf = [0; 1]; + assert_eq!(Ok(0), R.take(0).read(&mut buf)); + } }