From dd711f4deef316e31a4e4c609bcd56e08c9123cd Mon Sep 17 00:00:00 2001
From: jD91mZM2 <me@krake.one>
Date: Sat, 29 Sep 2018 15:04:58 +0200
Subject: [PATCH] Fix bug in fread

Bug discovered by @xTibor. Test and input data provided by him.
---
 src/header/stdio/mod.rs           | 17 ++++++++--------
 tests/Makefile                    |  1 +
 tests/expected/stdio/fread.stderr |  0
 tests/expected/stdio/fread.stdout | 32 +++++++++++++++++++++++++++++++
 tests/stdio/fread.c               | 21 ++++++++++++++++++++
 tests/stdio/fread.in              |  1 +
 6 files changed, 64 insertions(+), 8 deletions(-)
 create mode 100644 tests/expected/stdio/fread.stderr
 create mode 100644 tests/expected/stdio/fread.stdout
 create mode 100644 tests/stdio/fread.c
 create mode 100644 tests/stdio/fread.in

diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
index aa0da97d7..bf145326f 100644
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -71,20 +71,21 @@ pub struct FILE {
 }
 
 impl Read for FILE {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        if !buf.is_empty() {
+    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
+        if !out.is_empty() {
             if let Some(c) = self.unget.take() {
-                buf[0] = c;
+                out[0] = c;
                 return Ok(1);
             }
         }
 
-        if self.read_pos == self.read_size {
-            self.fill_buf()?;
-        }
+        let len = {
+            let buf = self.fill_buf()?;
+            let len = buf.len().min(out.len());
 
-        let len = buf.len().min(self.read_size);
-        buf[..len].copy_from_slice(&mut self.read_buf[..len]);
+            out[..len].copy_from_slice(&buf[..len]);
+            len
+        };
         self.consume(len);
         Ok(len)
     }
diff --git a/tests/Makefile b/tests/Makefile
index 34bc799f3..59e0834bc 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -17,6 +17,7 @@ EXPECT_BINS=\
 	stdio/all \
 	stdio/buffer \
 	stdio/fgets \
+	stdio/fread \
 	stdio/freopen \
 	stdio/fseek \
 	stdio/fwrite \
diff --git a/tests/expected/stdio/fread.stderr b/tests/expected/stdio/fread.stderr
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/expected/stdio/fread.stdout b/tests/expected/stdio/fread.stdout
new file mode 100644
index 000000000..f3fbf213b
--- /dev/null
+++ b/tests/expected/stdio/fread.stdout
@@ -0,0 +1,32 @@
+1
+22
+333
+4444
+55555
+666666
+7777777
+88888888
+999999999
+AAAAAAAAAA
+BBBBBBBBBBB
+CCCCCCCCCCCC
+DDDDDDDDDDDDD
+EEEEEEEEEEEEEE
+FFFFFFFFFFFFFFF
+0000000000000000
+11111111111111111
+222222222222222222
+3333333333333333333
+44444444444444444444
+555555555555555555555
+6666666666666666666666
+77777777777777777777777
+888888888888888888888888
+9999999999999999999999999
+AAAAAAAAAAAAAAAAAAAAAAAAAA
+BBBBBBBBBBBBBBBBBBBBBBBBBBB
+CCCCCCCCCCCCCCCCCCCCCCCCCCCC
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDD
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+00000000000000000000000000000000
diff --git a/tests/stdio/fread.c b/tests/stdio/fread.c
new file mode 100644
index 000000000..40b6f69e5
--- /dev/null
+++ b/tests/stdio/fread.c
@@ -0,0 +1,21 @@
+#include <errno.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+    FILE *fp = fopen("stdio/fread.in", "rb");
+
+    char buf[33] = { 0 };
+    for (int i = 1; i <= 32; ++i) {
+        if (fread(buf, 1, i, fp) < 0) {
+            perror("fread");
+            return 0;
+        }
+        buf[i] = 0;
+
+        printf("%s\n", buf);
+    }
+
+    fclose(fp);
+
+    return 0;
+}
diff --git a/tests/stdio/fread.in b/tests/stdio/fread.in
new file mode 100644
index 000000000..94b32220d
--- /dev/null
+++ b/tests/stdio/fread.in
@@ -0,0 +1 @@
+122333444455555666666777777788888888999999999AAAAAAAAAABBBBBBBBBBBCCCCCCCCCCCCDDDDDDDDDDDDDEEEEEEEEEEEEEEFFFFFFFFFFFFFFF0000000000000000111111111111111112222222222222222223333333333333333333444444444444444444445555555555555555555556666666666666666666666777777777777777777777778888888888888888888888889999999999999999999999999AAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000
-- 
GitLab