diff options
Diffstat (limited to 'lib/libc/stdio/fwrite.c')
-rw-r--r-- | lib/libc/stdio/fwrite.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c index cf52e42..acac943 100644 --- a/lib/libc/stdio/fwrite.c +++ b/lib/libc/stdio/fwrite.c @@ -37,6 +37,8 @@ static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93"; __FBSDID("$FreeBSD$"); #include "namespace.h" +#include <errno.h> +#include <stdint.h> #include <stdio.h> #include "un-namespace.h" #include "local.h" @@ -60,10 +62,24 @@ fwrite(buf, size, count, fp) /* * ANSI and SUSv2 require a return value of 0 if size or count are 0. */ - n = count * size; - if (n == 0) + if ((count == 0) || (size == 0)) return (0); + /* + * Check for integer overflow. As an optimization, first check that + * at least one of {count, size} is at least 2^16, since if both + * values are less than that, their product can't possible overflow + * (size_t is always at least 32 bits on FreeBSD). + */ + if (((count | size) > 0xFFFF) && + (count > SIZE_MAX / size)) { + errno = EINVAL; + fp->_flags |= __SERR; + return (0); + } + + n = count * size; + iov.iov_base = (void *)buf; uio.uio_resid = iov.iov_len = n; uio.uio_iov = &iov; |