diff options
author | ache <ache@FreeBSD.org> | 2001-08-31 12:55:22 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2001-08-31 12:55:22 +0000 |
commit | ae7b8fc7f6b359ec0633a545f7f08668243d2336 (patch) | |
tree | 652a448f600a36d10c845c506e6edf40933a4ebd | |
parent | c98f3a3f5e4b253474b2fcc952dc2e9c25725a0e (diff) | |
download | FreeBSD-src-ae7b8fc7f6b359ec0633a545f7f08668243d2336.zip FreeBSD-src-ae7b8fc7f6b359ec0633a545f7f08668243d2336.tar.gz |
Detect fp->_offset overflow on read
Use errno to catch negative seek with -1 offset
-rw-r--r-- | lib/libc/stdio/stdio.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c index 75f59c4..46dd2df 100644 --- a/lib/libc/stdio/stdio.c +++ b/lib/libc/stdio/stdio.c @@ -45,8 +45,9 @@ static const char rcsid[] = #include "namespace.h" #include <errno.h> #include <fcntl.h> -#include <unistd.h> +#include <limits.h> #include <stdio.h> +#include <unistd.h> #include "un-namespace.h" #include "local.h" @@ -65,10 +66,19 @@ __sread(cookie, buf, n) ret = _read(fp->_file, buf, (size_t)n); /* if the read succeeded, update the current offset */ - if (ret >= 0) - fp->_offset += ret; - else - fp->_flags &= ~__SOFF; /* paranoia */ + if (ret >= 0) { + if (fp->_flags & __SOFF) { + if (fp->_offset > OFF_MAX - ret) { + errno = EOVERFLOW; + ret = -1; + } else { + fp->_offset += ret; + return (ret); + } + } else + return (ret); + } + fp->_flags &= ~__SOFF; return (ret); } @@ -94,20 +104,24 @@ __sseek(cookie, offset, whence) { register FILE *fp = cookie; register off_t ret; + int serrno, errret; + serrno = errno; + errno = 0; ret = lseek(fp->_file, (off_t)offset, whence); + errret = errno; + if (errno == 0) + errno = serrno; /* * Disallow negative seeks per POSIX. * It is needed here to help upper level caller * (fseek) in the cases it can't detect. */ if (ret < 0) { - if (ret != -1) { - /* Resulting seek is negative! */ - ret = -1; + if (errret == 0) errno = EINVAL; - } fp->_flags &= ~__SOFF; + ret = -1; } else { fp->_flags |= __SOFF; fp->_offset = ret; |