From c753c50bb99745f057fe66fd339992c354ec5db5 Mon Sep 17 00:00:00 2001 From: robottoy Date: Fri, 14 Jul 2023 11:34:25 +0800 Subject: [PATCH] fix fread buffer overflow Issue:#I7L4P3 Test:libc-test Signed-off-by: robottoy Change-Id: I76d468a7f4e5bafd996447584928cfed6f7f54d5 --- .../functionalext/supplement/stdio/fread.c | 41 ++++++++++++++++++- porting/linux/user/src/stdio/__stdio_read.c | 11 +++-- porting/linux/user/src/stdio/fread.c | 3 +- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/libc-test/src/functionalext/supplement/stdio/fread.c b/libc-test/src/functionalext/supplement/stdio/fread.c index 067cb730..9e92e426 100644 --- a/libc-test/src/functionalext/supplement/stdio/fread.c +++ b/libc-test/src/functionalext/supplement/stdio/fread.c @@ -13,6 +13,8 @@ * limitations under the License. */ +#include +#include #include #include "functionalext.h" @@ -116,11 +118,48 @@ void fread_0400(void) remove(ptr); } +/** + * @tc.name : fread_0500 + * @tc.desc : Verify that the return value of syscall have been processed correctly + * @tc.level : Level 2 + */ +#define FREAD_0500_BUFSZ (4097) +void fread_0500(void) +{ + pid_t pid = fork(); + if (pid == -1) { + perror("fread_0500 fork:"); + exit(-1); + } + + /* child */ + if (pid == 0) { + /* make sure parent opening the status file */ + sleep(1); + exit(-1); + } + + char buf[FREAD_0500_BUFSZ] = {0}; + sprintf(buf, "/proc/%d/status", pid); + FILE *fStatus = fopen(buf, "rb"); + EXPECT_PTRNE("fread_0500", fStatus, NULL); + + /* wait child exit, and status file of child will disappear */ + int status = 0; + pid_t w = wait(&status); + + /* read >4K data from file, check if return correctly */ + size_t rsize = fread(buf, 1, FREAD_0500_BUFSZ, fStatus); + EXPECT_EQ("fread_0500", rsize, 0); + fclose(fStatus); +} + TEST_FUN G_Fun_Array[] = { fread_0100, fread_0200, fread_0300, fread_0400, + fread_0500, }; int main(int argc, char *argv[]) @@ -131,4 +170,4 @@ int main(int argc, char *argv[]) } return t_status; -} \ No newline at end of file +} diff --git a/porting/linux/user/src/stdio/__stdio_read.c b/porting/linux/user/src/stdio/__stdio_read.c index 2511e34b..dd681e0b 100644 --- a/porting/linux/user/src/stdio/__stdio_read.c +++ b/porting/linux/user/src/stdio/__stdio_read.c @@ -3,7 +3,12 @@ size_t __stdio_readx(FILE *f, unsigned char *buf, size_t len) { - return syscall(SYS_read, f->fd, buf, len); + ssize_t cnt = syscall(SYS_read, f->fd, buf, len); + if (cnt <= 0) { + f->flags |= cnt ? F_ERR : F_EOF; + return 0; + } + return cnt; } size_t __stdio_read(FILE *f, unsigned char *buf, size_t len) @@ -21,8 +26,8 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len) return 0; } if (cnt <= iov_buf[0].iov_len) { - return cnt; - } + return cnt; + } cnt -= iov_buf[0].iov_len; f->rpos = f->buf; f->rend = f->buf + cnt; diff --git a/porting/linux/user/src/stdio/fread.c b/porting/linux/user/src/stdio/fread.c index 6819a1eb..38b685c1 100644 --- a/porting/linux/user/src/stdio/fread.c +++ b/porting/linux/user/src/stdio/fread.c @@ -69,8 +69,7 @@ size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f) /* Read the remainder directly */ for (; l; l-=k, dest+=k) { k = f->readx(f, dest, l); - if (k <= 0) { - f->flags |= (k == 0 ? F_EOF : F_ERR); + if (!k) { break; } } -- GitLab