diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libc/stdio/fseek.3 | 16 | ||||
| -rw-r--r-- | lib/libc/stdio/fseek.c | 23 | ||||
| -rw-r--r-- | lib/libc/stdio/stdio.c | 19 | 
3 files changed, 45 insertions, 13 deletions
| diff --git a/lib/libc/stdio/fseek.3 b/lib/libc/stdio/fseek.3 index 9a58668013b6..b37aa176df1f 100644 --- a/lib/libc/stdio/fseek.3 +++ b/lib/libc/stdio/fseek.3 @@ -180,18 +180,12 @@ is not a seekable stream.  .It Bq Er EINVAL  The  .Fa whence -argument to -.Fn fseek -was not -.Dv SEEK_SET , -.Dv SEEK_END , -or -.Dv SEEK_CUR . +argument is invalid. +The resulting file-position +indicator would be set to a negative value.  .It Bq Er EOVERFLOW -For -.Fn ftell , -the resulting file offset would be a value which -cannot be represented correctly in an object of type long. +The resulting file offset would be a value which +cannot be represented correctly in an object of type requested.  .El  .Pp  The functions diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c index b4343501e6db..d311f7a5e1c2 100644 --- a/lib/libc/stdio/fseek.c +++ b/lib/libc/stdio/fseek.c @@ -132,12 +132,26 @@ _fseeko(fp, offset, whence)  		} else if (fp->_flags & __SWR && fp->_p != NULL)  			curoff += fp->_p - fp->_bf._base; +		if (offset > 0 && offset + (off_t)curoff < 0) { +			errno = EOVERFLOW; +			return (EOF); +		}  		offset += curoff; +		/* Disallow negative seeks per POSIX */ +		if (offset < 0) { +			errno = EINVAL; +			return (EOF); +		}  		whence = SEEK_SET;  		havepos = 1;  		break;  	case SEEK_SET: +		/* Disallow negative seeks per POSIX */ +		if (offset < 0) { +			errno = EINVAL; +			return (EOF); +		}  	case SEEK_END:  		curoff = 0;		/* XXX just to keep gcc quiet */  		havepos = 0; @@ -180,7 +194,16 @@ _fseeko(fp, offset, whence)  	else {  		if (_fstat(fp->_file, &st))  			goto dumb; +		if (offset > 0 && st.st_size + offset < 0) { +			errno = EOVERFLOW; +			return (EOF); +		}  		target = st.st_size + offset; +		/* Disallow negative seeks per POSIX */ +		if ((off_t)target < 0) { +			errno = EINVAL; +			return (EOF); +		}  	}  	if (!havepos) { diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c index 57be5bb42140..58fafcbc170f 100644 --- a/lib/libc/stdio/stdio.c +++ b/lib/libc/stdio/stdio.c @@ -43,6 +43,7 @@ static const char rcsid[] =  #endif /* LIBC_SCCS and not lint */  #include "namespace.h" +#include <errno.h>  #include <fcntl.h>  #include <unistd.h>  #include <stdio.h> @@ -94,10 +95,24 @@ __sseek(cookie, offset, whence)  	register FILE *fp = cookie;  	register off_t ret; +	/* +	 * Disallow negative seeks per POSIX. +	 * It is needed here to help upper level caller +	 * (fseek) in the cases it can't detect. +	 */ +	if (whence == SEEK_SET && (off_t)offset < 0) { +		errno = EINVAL; +		return (-1); +	}  	ret = lseek(fp->_file, (off_t)offset, whence); -	if (ret == -1) +	if (ret < 0) { +		if (ret != -1) { +			/* Resulting seek is negative! */ +			ret = -1; +			errno = EINVAL; +		}  		fp->_flags &= ~__SOFF; -	else { +	} else {  		fp->_flags |= __SOFF;  		fp->_offset = ret;  	} | 
