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