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 | #ifndef SIZE_MAX |
48 | #define SIZE_MAX UINTPTR_MAX |
49 | #endif |
50 | |
51 | /* |
52 | * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX |
53 | * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW |
54 | */ |
55 | #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) |
56 | |
57 | void * |
58 | openbsd_reallocarray(void *optr, size_t nmemb, size_t size) |
59 | { |
60 | if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && |
61 | nmemb > 0 && SIZE_MAX / nmemb < size) { |
62 | errno = ENOMEM; |
63 | return NULL; |
64 | } |
65 | /* |
66 | * Head off variations in realloc behavior on different |
67 | * platforms (reported by MarkR <mrogers6@users.sf.net>) |
68 | * |
69 | * The behaviour of reallocarray is implementation-defined if |
70 | * nmemb or size is zero. It can return NULL or non-NULL |
71 | * depending on the platform. |
72 | * https://www.securecoding.cert.org/confluence/display/c/MEM04-C.Beware+of+zero-lengthallocations |
73 | * |
74 | * Here are some extracts from realloc man pages on different platforms. |
75 | * |
76 | * void realloc( void memblock, size_t size ); |
77 | * |
78 | * Windows: |
79 | * |
80 | * If there is not enough available memory to expand the block |
81 | * to the given size, the original block is left unchanged, |
82 | * and NULL is returned. If size is zero, then the block |
83 | * pointed to by memblock is freed; the return value is NULL, |
84 | * and memblock is left pointing at a freed block. |
85 | * |
86 | * OpenBSD: |
87 | * |
88 | * If size or nmemb is equal to 0, a unique pointer to an |
89 | * access protected, zero sized object is returned. Access via |
90 | * this pointer will generate a SIGSEGV exception. |
91 | * |
92 | * Linux: |
93 | * |
94 | * If size was equal to 0, either NULL or a pointer suitable |
95 | * to be passed to free() is returned. |
96 | * |
97 | * OS X: |
98 | * |
99 | * If size is zero and ptr is not NULL, a new, minimum sized |
100 | * object is allocated and the original object is freed. |
101 | * |
102 | * It looks like images with zero width or height can trigger |
103 | * this, and fuzzing behaviour will differ by platform, so |
104 | * fuzzing on one platform may not detect zero-size allocation |
105 | * problems on other platforms. |
106 | */ |
107 | if (size == 0 || nmemb == 0) |
108 | return NULL; |
109 | return realloc(optr, size * nmemb); |
110 | } |
111 | |