summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/fwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdio/fwrite.c')
-rw-r--r--lib/libc/stdio/fwrite.c20
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;
OpenPOWER on IntegriCloud