summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/ftell.c
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2001-08-30 19:54:04 +0000
committerache <ache@FreeBSD.org>2001-08-30 19:54:04 +0000
commitf8e201c54991f8ae822c054363d85332f5b9a013 (patch)
tree5f2a09e41a33b0f67a9f06e3d8f9ae0423539ed0 /lib/libc/stdio/ftell.c
parent0c27263b4a639850fd1858db4b63b142a3b57a27 (diff)
downloadFreeBSD-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.c40
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);
OpenPOWER on IntegriCloud