]> eyrie.org Git - kerberos/krb5-strength.git/blob - portable/reallocarray.c
Merge pull request #4 from dariaphoebe/main
[kerberos/krb5-strength.git] / portable / reallocarray.c
1 /*
2  * Replacement for a missing reallocarray.
3  *
4  * Provides the same functionality as the OpenBSD library function
5  * reallocarray for those systems that don't have it.  This function is the
6  * same as realloc, but takes the size arguments in the same form as calloc
7  * and checks for overflow so that the caller doesn't need to.
8  *
9  * The canonical version of this file is maintained in the rra-c-util package,
10  * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
11  *
12  * Written by Russ Allbery <eagle@eyrie.org>
13  * Copyright 2017 Russ Allbery <eagle@eyrie.org>
14  * Copyright 2014
15  *     The Board of Trustees of the Leland Stanford Junior University
16  *
17  * Copying and distribution of this file, with or without modification, are
18  * permitted in any medium without royalty provided the copyright notice and
19  * this notice are preserved.  This file is offered as-is, without any
20  * warranty.
21  *
22  * SPDX-License-Identifier: FSFAP
23  */
24
25 #include <config.h>
26 #include <portable/system.h>
27
28 #include <errno.h>
29
30 /*
31  * If we're running the test suite, rename reallocarray to avoid conflicts
32  * with the system version.  #undef it first because some systems may define
33  * it to another name.
34  */
35 #if TESTING
36 #    undef reallocarray
37 #    define reallocarray test_reallocarray
38 void *test_reallocarray(void *, size_t, size_t);
39 #endif
40
41 /*
42  * nmemb * size cannot overflow if both are smaller than sqrt(SIZE_MAX).  We
43  * can calculate that value statically by using 2^(sizeof(size_t) * 8) as the
44  * value of SIZE_MAX and then taking the square root, which gives
45  * 2^(sizeof(size_t) * 4).  Compute the exponentiation with shift.
46  */
47 #define CHECK_THRESHOLD (1UL << (sizeof(size_t) * 4))
48
49 void *
50 reallocarray(void *ptr, size_t nmemb, size_t size)
51 {
52     if (nmemb >= CHECK_THRESHOLD || size >= CHECK_THRESHOLD)
53         if (nmemb > 0 && SIZE_MAX / nmemb <= size) {
54             errno = ENOMEM;
55             return NULL;
56         }
57
58     /* Avoid a zero-size allocation. */
59     if (nmemb == 0 || size == 0) {
60         nmemb = 1;
61         size = 1;
62     }
63     return realloc(ptr, nmemb * size);
64 }