From 59f388a67f9319d79d123a42feecf8a6efba764e Mon Sep 17 00:00:00 2001 From: Jakub Jermar Date: Tue, 4 Apr 2017 22:56:47 +0200 Subject: [PATCH] Fail legacy interfaces if the position is too large for them to represent HelenOS interfaces support unsigned 64-bit file sizes and offsets. This is in contrast with C99-ish and POSIX-ish interfaces in libc and libposix. The legacy API emulation internally uses the native unsigned 64-bit file sizes and positions and so it may happen that a returned file size or offset are bigger than the legacy interface can represent. We choose to report failure in such a case in order to avoid returning wrong results. --- uspace/lib/c/generic/io/io.c | 4 ++++ uspace/lib/posix/source/sys/stat.c | 17 ++++++++++++----- uspace/lib/posix/source/unistd.c | 5 +++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/uspace/lib/c/generic/io/io.c b/uspace/lib/c/generic/io/io.c index d55c71052..274497e0b 100644 --- a/uspace/lib/c/generic/io/io.c +++ b/uspace/lib/c/generic/io/io.c @@ -833,6 +833,10 @@ int fseek(FILE *stream, off64_t offset, int whence) off64_t ftell(FILE *stream) { + /* The native position is too large for the C99-ish interface. */ + if (stream->pos - stream->ungetc_chars > INT64_MAX) + return EOF; + if (stream->error) return EOF; diff --git a/uspace/lib/posix/source/sys/stat.c b/uspace/lib/posix/source/sys/stat.c index a257bb3c4..c16c98352 100644 --- a/uspace/lib/posix/source/sys/stat.c +++ b/uspace/lib/posix/source/sys/stat.c @@ -48,8 +48,10 @@ * * @param dest POSIX stat struct. * @param src HelenOS stat struct. + * + * @return 0 on success, -1 on error. */ -static void stat_to_posix(struct posix_stat *dest, struct stat *src) +static int stat_to_posix(struct posix_stat *dest, struct stat *src) { memset(dest, 0, sizeof(struct posix_stat)); @@ -67,6 +69,13 @@ static void stat_to_posix(struct posix_stat *dest, struct stat *src) dest->st_nlink = src->lnkcnt; dest->st_size = src->size; + + if (src->size > INT64_MAX) { + errno = ERANGE; + return -1; + } + + return 0; } /** @@ -82,8 +91,7 @@ int posix_fstat(int fd, struct posix_stat *st) int rc = rcerrno(vfs_stat, fd, &hst); if (rc < 0) return -1; - stat_to_posix(st, &hst); - return 0; + return stat_to_posix(st, &hst); } /** @@ -112,8 +120,7 @@ int posix_stat(const char *restrict path, struct posix_stat *restrict st) int rc = rcerrno(vfs_stat_path, path, &hst); if (rc < 0) return -1; - stat_to_posix(st, &hst); - return 0; + return stat_to_posix(st, &hst); } /** diff --git a/uspace/lib/posix/source/unistd.c b/uspace/lib/posix/source/unistd.c index 07d1cb80a..1b1bc1788 100644 --- a/uspace/lib/posix/source/unistd.c +++ b/uspace/lib/posix/source/unistd.c @@ -244,6 +244,11 @@ posix_off_t posix_lseek(int fildes, posix_off_t offset, int whence) posix_pos[fildes] = st.size + offset; break; } + if (posix_pos[fildes] > INT64_MAX) { + /* The native width is too large for the POSIX interface. */ + errno = ERANGE; + return -1; + } return posix_pos[fildes]; } -- 2.11.4.GIT