1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*    $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $    */
  26 /*
  27  * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
  28  *
  29  * Permission to use, copy, modify, and distribute this software for any
  30  * purpose with or without fee is hereby granted, provided that the above
  31  * copyright notice and this permission notice appear in all copies.
  32  *
  33  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  34  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  35  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  36  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  37  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  38  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  39  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  40  */
  41 
  42 #include <sys/types.h>
  43 #include <errno.h>
  44 #include <stdint.h>
  45 #include <stdlib.h>
  46 
  47 /*
  48  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
  49  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
  50  */
  51 #define MUL_NO_OVERFLOW    ((size_t)1 << (sizeof(size_t) * 4))
  52 
  53 void *
  54 reallocarray(void *optr, size_t nmemb, size_t size)
  55 {
  56     if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
  57         nmemb > 0 && SIZE_MAX / nmemb < size) {
  58         errno = ENOMEM;
  59         return NULL;
  60     }
  61     /*
  62      * Head off variations in realloc behavior on different
  63      * platforms (reported by MarkR <mrogers6@users.sf.net>)
  64      *
  65      * The behaviour of reallocarray is implementation-defined if
  66      * nmemb or size is zero. It can return NULL or non-NULL
  67      * depending on the platform.
  68      * https://www.securecoding.cert.org/confluence/display/c/MEM04-C.Beware+of+zero-lengthallocations
  69      *
  70      * Here are some extracts from realloc man pages on different platforms.
  71      *
  72      * void realloc( void memblock, size_t size );
  73      *
  74      * Windows:
  75      *
  76      * If there is not enough available memory to expand the block
  77      * to the given size, the original block is left unchanged,
  78      * and NULL is returned.  If size is zero, then the block
  79      * pointed to by memblock is freed; the return value is NULL,
  80      * and memblock is left pointing at a freed block.
  81      *
  82      * OpenBSD:
  83      *
  84      * If size or nmemb is equal to 0, a unique pointer to an
  85      * access protected, zero sized object is returned. Access via
  86      * this pointer will generate a SIGSEGV exception.
  87      *
  88      * Linux:
  89      *
  90      * If size was equal to 0, either NULL or a pointer suitable
  91      * to be passed to free() is returned.
  92      *
  93      * OS X:
  94      *
  95      * If size is zero and ptr is not NULL, a new, minimum sized
  96      * object is allocated and the original object is freed.
  97      *
  98      * It looks like images with zero width or height can trigger
  99      * this, and fuzzing behaviour will differ by platform, so
 100      * fuzzing on one platform may not detect zero-size allocation
 101      * problems on other platforms.
 102      */
 103     if (size == 0 || nmemb == 0)
 104         return NULL;
 105     return realloc(optr, size * nmemb);
 106 }