1f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes/* $OpenBSD: fread.c,v 1.12 2014/05/01 16:40:36 deraadt Exp $ */ 29d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes/*- 39d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * Copyright (c) 1990, 1993 49d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * The Regents of the University of California. All rights reserved. 59d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * 69d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * This code is derived from software contributed to Berkeley by 79d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * Chris Torek. 89d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * 99d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * Redistribution and use in source and binary forms, with or without 109d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * modification, are permitted provided that the following conditions 119d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * are met: 129d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * 1. Redistributions of source code must retain the above copyright 139d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * notice, this list of conditions and the following disclaimer. 149d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 159d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * notice, this list of conditions and the following disclaimer in the 169d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * documentation and/or other materials provided with the distribution. 179d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * 3. Neither the name of the University nor the names of its contributors 189d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * may be used to endorse or promote products derived from this software 199d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * without specific prior written permission. 209d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * 219d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * SUCH DAMAGE. 329d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes */ 339d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes 349d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes#include <stdio.h> 359d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes#include <string.h> 36f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes#include <stdint.h> 37f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes#include <errno.h> 389d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes#include "local.h" 399d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes 40f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) 41f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes 429d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughessize_t 439d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughesfread(void *buf, size_t size, size_t count, FILE *fp) 449d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes{ 459d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes size_t resid; 469d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes char *p; 479d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes int r; 489d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes size_t total; 499d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes 509d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes /* 51f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes * Extension: Catch integer overflow 52f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes */ 53f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) && 54f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes size > 0 && SIZE_MAX / size < count) { 55f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes errno = EOVERFLOW; 56f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes fp->_flags |= __SERR; 57f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes return (0); 58f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes } 59f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes 60f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes /* 619d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes * ANSI and SUSv2 require a return value of 0 if size or count are 0. 629d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes */ 639d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes if ((resid = count * size) == 0) 649d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes return (0); 659d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes FLOCKFILE(fp); 669d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes _SET_ORIENTATION(fp, -1); 679d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes if (fp->_r < 0) 689d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes fp->_r = 0; 699d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes total = resid; 709d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes p = buf; 719d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes while (resid > (r = fp->_r)) { 729d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes (void)memcpy((void *)p, (void *)fp->_p, (size_t)r); 739d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes fp->_p += r; 749d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes /* fp->_r = 0 ... done in __srefill */ 759d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes p += r; 769d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes resid -= r; 779d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes if (__srefill(fp)) { 789d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes /* no more input: return partial result */ 799d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes FUNLOCKFILE(fp); 809d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes return ((total - resid) / size); 819d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes } 829d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes } 839d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes (void)memcpy((void *)p, (void *)fp->_p, resid); 849d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes fp->_r -= resid; 859d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes fp->_p += resid; 869d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes FUNLOCKFILE(fp); 879d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes return (count); 889d3c2dd11f5e796cd814cddc5b907494f859058eElliott Hughes} 89