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 }