Merge "Switch to current upstream OpenBSD fwrite.c."

This commit is contained in:
Elliott Hughes 2014-05-04 03:20:31 +00:00 committed by Gerrit Code Review
commit 640b4a5a64
3 changed files with 27 additions and 34 deletions

View file

@ -223,7 +223,6 @@ libc_upstream_freebsd_src_files := \
upstream-freebsd/lib/libc/stdio/fclose.c \ upstream-freebsd/lib/libc/stdio/fclose.c \
upstream-freebsd/lib/libc/stdio/flags.c \ upstream-freebsd/lib/libc/stdio/flags.c \
upstream-freebsd/lib/libc/stdio/fopen.c \ upstream-freebsd/lib/libc/stdio/fopen.c \
upstream-freebsd/lib/libc/stdio/fwrite.c \
upstream-freebsd/lib/libc/stdio/makebuf.c \ upstream-freebsd/lib/libc/stdio/makebuf.c \
upstream-freebsd/lib/libc/stdio/mktemp.c \ upstream-freebsd/lib/libc/stdio/mktemp.c \
upstream-freebsd/lib/libc/stdio/setvbuf.c \ upstream-freebsd/lib/libc/stdio/setvbuf.c \
@ -388,6 +387,7 @@ libc_upstream_openbsd_src_files := \
upstream-openbsd/lib/libc/stdio/fwalk.c \ upstream-openbsd/lib/libc/stdio/fwalk.c \
upstream-openbsd/lib/libc/stdio/fwide.c \ upstream-openbsd/lib/libc/stdio/fwide.c \
upstream-openbsd/lib/libc/stdio/fwprintf.c \ upstream-openbsd/lib/libc/stdio/fwprintf.c \
upstream-openbsd/lib/libc/stdio/fwrite.c \
upstream-openbsd/lib/libc/stdio/fwscanf.c \ upstream-openbsd/lib/libc/stdio/fwscanf.c \
upstream-openbsd/lib/libc/stdio/getc.c \ upstream-openbsd/lib/libc/stdio/getc.c \
upstream-openbsd/lib/libc/stdio/getchar.c \ upstream-openbsd/lib/libc/stdio/getchar.c \

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $ */ /* $OpenBSD: fvwrite.h,v 1.6 2013/11/12 07:04:35 deraadt Exp $ */
/*- /*-
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
@ -36,7 +36,7 @@
* I/O descriptors for __sfvwrite(). * I/O descriptors for __sfvwrite().
*/ */
struct __siov { struct __siov {
const void *iov_base; void *iov_base;
size_t iov_len; size_t iov_len;
}; };
struct __suio { struct __suio {
@ -46,3 +46,4 @@ struct __suio {
}; };
extern int __sfvwrite(FILE *, struct __suio *); extern int __sfvwrite(FILE *, struct __suio *);
wint_t __fputwc_unlock(wchar_t wc, FILE *fp);

View file

@ -1,3 +1,4 @@
/* $OpenBSD: fwrite.c,v 1.11 2014/05/01 16:40:36 deraadt Exp $ */
/*- /*-
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
@ -30,67 +31,58 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include "un-namespace.h" #include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include "local.h" #include "local.h"
#include "fvwrite.h" #include "fvwrite.h"
#include "libc_private.h"
#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
/* /*
* Write `count' objects (each size `size') from memory to the given file. * Write `count' objects (each size `size') from memory to the given file.
* Return the number of whole objects written. * Return the number of whole objects written.
*/ */
size_t size_t
fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp) fwrite(const void *buf, size_t size, size_t count, FILE *fp)
{ {
size_t n; size_t n;
struct __suio uio; struct __suio uio;
struct __siov iov; struct __siov iov;
int ret;
/* /*
* ANSI and SUSv2 require a return value of 0 if size or count are 0. * Extension: Catch integer overflow
*/ */
if ((count == 0) || (size == 0)) if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) &&
return (0); size > 0 && SIZE_MAX / size < count) {
errno = EOVERFLOW;
/*
* 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; fp->_flags |= __SERR;
return (0); return (0);
} }
n = count * size; /*
* ANSI and SUSv2 require a return value of 0 if size or count are 0.
*/
if ((n = count * size) == 0)
return (0);
iov.iov_base = (void *)buf; iov.iov_base = (void *)buf;
uio.uio_resid = iov.iov_len = n; uio.uio_resid = iov.iov_len = n;
uio.uio_iov = &iov; uio.uio_iov = &iov;
uio.uio_iovcnt = 1; uio.uio_iovcnt = 1;
FLOCKFILE(fp);
ORIENT(fp, -1);
/* /*
* The usual case is success (__sfvwrite returns 0); * The usual case is success (__sfvwrite returns 0);
* skip the divide if this happens, since divides are * skip the divide if this happens, since divides are
* generally slow and since this occurs whenever size==0. * generally slow and since this occurs whenever size==0.
*/ */
if (__sfvwrite(fp, &uio) != 0) FLOCKFILE(fp);
count = (n - uio.uio_resid) / size; _SET_ORIENTATION(fp, -1);
ret = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp); FUNLOCKFILE(fp);
return (count); if (ret == 0)
return (count);
return ((n - uio.uio_resid) / size);
} }