diff options
author | ache <ache@FreeBSD.org> | 2001-08-30 19:54:04 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2001-08-30 19:54:04 +0000 |
commit | f8e201c54991f8ae822c054363d85332f5b9a013 (patch) | |
tree | 5f2a09e41a33b0f67a9f06e3d8f9ae0423539ed0 /lib/libc/stdio/ftell.c | |
parent | 0c27263b4a639850fd1858db4b63b142a3b57a27 (diff) | |
download | FreeBSD-src-f8e201c54991f8ae822c054363d85332f5b9a013.zip FreeBSD-src-f8e201c54991f8ae822c054363d85332f5b9a013.tar.gz |
Add more EOVERFLOW checks.
When file offset tends to be negative due to internal and ungetc buffers
additions counted, try to discard some ungetc data first, then return EBADF.
Later one can happens if lseek(fileno(fd),...) called f.e. POSIX says that
ungetc beyond beginning of the file results are undefined, so we can just
discard some of ungetc data in that case.
Don't rely on gcc cast when checking for overflow, use OFF_MAX.
Cosmetique.
Diffstat (limited to 'lib/libc/stdio/ftell.c')
-rw-r--r-- | lib/libc/stdio/ftell.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c index e4a4e11..38a164e 100644 --- a/lib/libc/stdio/ftell.c +++ b/lib/libc/stdio/ftell.c @@ -44,8 +44,9 @@ static const char rcsid[] = #include "namespace.h" #include <sys/types.h> -#include <stdio.h> #include <errno.h> +#include <limits.h> +#include <stdio.h> #include "un-namespace.h" #include "local.h" #include "libc_private.h" @@ -58,8 +59,9 @@ ftell(fp) register FILE *fp; { register off_t rv; + rv = ftello(fp); - if ((long)rv != rv) { + if (rv > LONG_MAX) { errno = EOVERFLOW; return (-1); } @@ -74,10 +76,11 @@ ftello(fp) register FILE *fp; { register fpos_t pos; + size_t n; if (fp->_seek == NULL) { errno = ESPIPE; /* historic practice */ - return (-1L); + return (-1); } FLOCKFILE(fp); @@ -91,7 +94,7 @@ ftello(fp) pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR); if (pos == -1) { FUNLOCKFILE(fp); - return (pos); + return (-1); } } if (fp->_flags & __SRD) { @@ -101,15 +104,38 @@ ftello(fp) * smaller than that in the underlying object. */ pos -= fp->_r; - if (HASUB(fp)) + if (pos < 0) { + if (HASUB(fp)) { + fp->_p -= pos; + fp->_r += pos; + pos = 0; + } else { + errno = EBADF; + FUNLOCKFILE(fp); + return (-1); + } + } + if (HASUB(fp)) { pos -= fp->_ur; - } else if (fp->_flags & __SWR && fp->_p != NULL) { + if (pos < 0) { + errno = EBADF; + FUNLOCKFILE(fp); + return (-1); + } + } + } else if ((fp->_flags & __SWR) && fp->_p != NULL) { /* * Writing. Any buffered characters cause the * position to be greater than that in the * underlying object. */ - pos += fp->_p - fp->_bf._base; + n = fp->_p - fp->_bf._base; + if (pos > OFF_MAX - n) { + FUNLOCKFILE(fp); + errno = EOVERFLOW; + return (-1); + } + pos += n; } FUNLOCKFILE(fp); return (pos); |