]> git.lizzy.rs Git - rust.git/commitdiff
Fix io::Take behavior with limit 0
authorSteven Fackler <sfackler@gmail.com>
Sat, 21 Feb 2015 19:15:58 +0000 (11:15 -0800)
committerSteven Fackler <sfackler@gmail.com>
Sat, 21 Feb 2015 19:15:58 +0000 (11:15 -0800)
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

index c38d52161c96e8484ab8e656b224d29f7f9595e8..5e810926ee4fbd2f178bdca8da8e3ee91087b740 100644 (file)
@@ -669,6 +669,11 @@ pub fn limit(&self) -> u64 { self.limit }
 
 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 @@ fn next(&mut self) -> Option<Result<String>> {
 mod tests {
     use prelude::v1::*;
     use io::prelude::*;
+    use io;
     use super::Cursor;
 
     #[test]
@@ -943,4 +949,18 @@ fn read_to_string() {
         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));
+    }
 }