/src/giflib-code/openbsd-reallocarray.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * SPDX-FileCopyrightText: Copyright (C) 2008 Otto Moerbeek <otto@drijf.net>  | 
3  |  |  * SPDX-License-Identifier: MIT  | 
4  |  |  */  | 
5  |  |  | 
6  |  | #include <errno.h>  | 
7  |  | #include <stdint.h>  | 
8  |  | #include <stdlib.h>  | 
9  |  | #include <sys/types.h>  | 
10  |  |  | 
11  |  | #ifndef SIZE_MAX  | 
12  |  | #define SIZE_MAX UINTPTR_MAX  | 
13  |  | #endif  | 
14  |  |  | 
15  |  | /*  | 
16  |  |  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX  | 
17  |  |  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW  | 
18  |  |  */  | 
19  | 0  | #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))  | 
20  |  |  | 
21  | 0  | void *openbsd_reallocarray(void *optr, size_t nmemb, size_t size) { | 
22  | 0  |   if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&  | 
23  | 0  |       nmemb > 0 && SIZE_MAX / nmemb < size) { | 
24  | 0  |     errno = ENOMEM;  | 
25  | 0  |     return NULL;  | 
26  | 0  |   }  | 
27  |  |   /*  | 
28  |  |    * Head off variations in realloc behavior on different  | 
29  |  |    * platforms (reported by MarkR <mrogers6@users.sf.net>)  | 
30  |  |    *  | 
31  |  |    * The behaviour of reallocarray is implementation-defined if  | 
32  |  |    * nmemb or size is zero. It can return NULL or non-NULL  | 
33  |  |    * depending on the platform.  | 
34  |  |    * https://www.securecoding.cert.org/confluence/display/c/MEM04-C.Beware+of+zero-lengthallocations  | 
35  |  |    *  | 
36  |  |    * Here are some extracts from realloc man pages on different platforms.  | 
37  |  |    *  | 
38  |  |    * void realloc( void memblock, size_t size );  | 
39  |  |    *  | 
40  |  |    * Windows:  | 
41  |  |    *  | 
42  |  |    * If there is not enough available memory to expand the block  | 
43  |  |    * to the given size, the original block is left unchanged,  | 
44  |  |    * and NULL is returned.  If size is zero, then the block  | 
45  |  |    * pointed to by memblock is freed; the return value is NULL,  | 
46  |  |    * and memblock is left pointing at a freed block.  | 
47  |  |    *  | 
48  |  |    * OpenBSD:  | 
49  |  |    *  | 
50  |  |    * If size or nmemb is equal to 0, a unique pointer to an  | 
51  |  |    * access protected, zero sized object is returned. Access via  | 
52  |  |    * this pointer will generate a SIGSEGV exception.  | 
53  |  |    *  | 
54  |  |    * Linux:  | 
55  |  |    *  | 
56  |  |    * If size was equal to 0, either NULL or a pointer suitable  | 
57  |  |    * to be passed to free() is returned.  | 
58  |  |    *  | 
59  |  |    * OS X:  | 
60  |  |    *  | 
61  |  |    * If size is zero and ptr is not NULL, a new, minimum sized  | 
62  |  |    * object is allocated and the original object is freed.  | 
63  |  |    *  | 
64  |  |    * It looks like images with zero width or height can trigger  | 
65  |  |    * this, and fuzzing behaviour will differ by platform, so  | 
66  |  |    * fuzzing on one platform may not detect zero-size allocation  | 
67  |  |    * problems on other platforms.  | 
68  |  |    */  | 
69  | 0  |   if (size == 0 || nmemb == 0) { | 
70  | 0  |     return NULL;  | 
71  | 0  |   }  | 
72  | 0  |   return realloc(optr, size * nmemb);  | 
73  | 0  | }  |