/src/tor/src/lib/malloc/malloc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2003, Roger Dingledine |
2 | | * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. |
3 | | * Copyright (c) 2007-2021, The Tor Project, Inc. */ |
4 | | /* See LICENSE for licensing information */ |
5 | | |
6 | | /** |
7 | | * \file malloc.c |
8 | | * \brief Wrappers for C malloc code, and replacements for items that |
9 | | * may be missing. |
10 | | **/ |
11 | | |
12 | | #include "orconfig.h" |
13 | | |
14 | | #include <stdlib.h> |
15 | | #include <string.h> |
16 | | |
17 | | #include "lib/testsupport/testsupport.h" |
18 | | #define UTIL_MALLOC_PRIVATE |
19 | | #include "lib/malloc/malloc.h" |
20 | | #include "lib/cc/torint.h" |
21 | | #include "lib/err/torerr.h" |
22 | | |
23 | | #ifdef __clang_analyzer__ |
24 | | #undef MALLOC_ZERO_WORKS |
25 | | #endif |
26 | | |
27 | | /** Allocate a chunk of <b>size</b> bytes of memory, and return a pointer to |
28 | | * result. On error, log and terminate the process. (Same as malloc(size), |
29 | | * but never returns NULL.) |
30 | | */ |
31 | | void * |
32 | | tor_malloc_(size_t size) |
33 | 255M | { |
34 | 255M | void *result; |
35 | | |
36 | 255M | raw_assert(size < SIZE_T_CEILING); |
37 | | |
38 | | #ifndef MALLOC_ZERO_WORKS |
39 | | /* Some libc mallocs don't work when size==0. Override them. */ |
40 | | if (size==0) { |
41 | | size=1; |
42 | | } |
43 | | #endif /* !defined(MALLOC_ZERO_WORKS) */ |
44 | | |
45 | 255M | result = raw_malloc(size); |
46 | | |
47 | 255M | if (PREDICT_UNLIKELY(result == NULL)) { |
48 | | /* LCOV_EXCL_START */ |
49 | | /* If these functions die within a worker process, they won't call |
50 | | * spawn_exit, but that's ok, since the parent will run out of memory soon |
51 | | * anyway. */ |
52 | 0 | raw_assert_unreached_msg("Out of memory on malloc(). Dying."); |
53 | | /* LCOV_EXCL_STOP */ |
54 | 0 | } |
55 | 255M | return result; |
56 | 255M | } |
57 | | |
58 | | /** Allocate a chunk of <b>size</b> bytes of memory, fill the memory with |
59 | | * zero bytes, and return a pointer to the result. Log and terminate |
60 | | * the process on error. (Same as calloc(size,1), but never returns NULL.) |
61 | | */ |
62 | | void * |
63 | | tor_malloc_zero_(size_t size) |
64 | 72.9M | { |
65 | | /* You may ask yourself, "wouldn't it be smart to use calloc instead of |
66 | | * malloc+memset? Perhaps libc's calloc knows some nifty optimization trick |
67 | | * we don't!" Indeed it does, but its optimizations are only a big win when |
68 | | * we're allocating something very big (it knows if it just got the memory |
69 | | * from the OS in a pre-zeroed state). We don't want to use tor_malloc_zero |
70 | | * for big stuff, so we don't bother with calloc. */ |
71 | 72.9M | void *result = tor_malloc_(size); |
72 | 72.9M | memset(result, 0, size); |
73 | 72.9M | return result; |
74 | 72.9M | } |
75 | | |
76 | | /* The square root of SIZE_MAX + 1. If a is less than this, and b is less |
77 | | * than this, then a*b is less than SIZE_MAX. (For example, if size_t is |
78 | | * 32 bits, then SIZE_MAX is 0xffffffff and this value is 0x10000. If a and |
79 | | * b are less than this, then their product is at most (65535*65535) == |
80 | | * 0xfffe0001. */ |
81 | 3.26M | #define SQRT_SIZE_MAX_P1 (((size_t)1) << (sizeof(size_t)*4)) |
82 | | |
83 | | /** Return non-zero if and only if the product of the arguments is exact, |
84 | | * and cannot overflow. */ |
85 | | STATIC int |
86 | | size_mul_check(const size_t x, const size_t y) |
87 | 1.63M | { |
88 | | /* This first check is equivalent to |
89 | | (x < SQRT_SIZE_MAX_P1 && y < SQRT_SIZE_MAX_P1) |
90 | | |
91 | | Rationale: if either one of x or y is >= SQRT_SIZE_MAX_P1, then it |
92 | | will have some bit set in its most significant half. |
93 | | */ |
94 | 1.63M | return ((x|y) < SQRT_SIZE_MAX_P1 || |
95 | 1.63M | y == 0 || |
96 | 1.63M | x <= SIZE_MAX / y); |
97 | 1.63M | } |
98 | | |
99 | | /** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill |
100 | | * the memory with zero bytes, and return a pointer to the result. |
101 | | * Log and terminate the process on error. (Same as |
102 | | * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.) |
103 | | * The second argument (<b>size</b>) should preferably be non-zero |
104 | | * and a compile-time constant. |
105 | | */ |
106 | | void * |
107 | | tor_calloc_(size_t nmemb, size_t size) |
108 | 1.46M | { |
109 | 1.46M | raw_assert(size_mul_check(nmemb, size)); |
110 | 1.46M | return tor_malloc_zero_((nmemb * size)); |
111 | 1.46M | } |
112 | | |
113 | | /** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b> |
114 | | * bytes long; return the new memory block. On error, log and |
115 | | * terminate. (Like realloc(ptr,size), but never returns NULL.) |
116 | | */ |
117 | | void * |
118 | | tor_realloc_(void *ptr, size_t size) |
119 | 168k | { |
120 | 168k | void *result; |
121 | | |
122 | 168k | raw_assert(size < SIZE_T_CEILING); |
123 | | |
124 | | #ifndef MALLOC_ZERO_WORKS |
125 | | /* Some libc mallocs don't work when size==0. Override them. */ |
126 | | if (size==0) { |
127 | | size=1; |
128 | | } |
129 | | #endif /* !defined(MALLOC_ZERO_WORKS) */ |
130 | | |
131 | 168k | result = raw_realloc(ptr, size); |
132 | | |
133 | 168k | if (PREDICT_UNLIKELY(result == NULL)) { |
134 | | /* LCOV_EXCL_START */ |
135 | 0 | raw_assert_unreached_msg("Out of memory on realloc(). Dying."); |
136 | | /* LCOV_EXCL_STOP */ |
137 | 0 | } |
138 | 168k | return result; |
139 | 168k | } |
140 | | |
141 | | /** |
142 | | * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for |
143 | | * overflow. Unlike other allocation functions, return NULL on overflow. |
144 | | */ |
145 | | void * |
146 | | tor_reallocarray_(void *ptr, size_t sz1, size_t sz2) |
147 | 168k | { |
148 | | /* XXXX we can make this return 0, but we would need to check all the |
149 | | * reallocarray users. */ |
150 | 168k | raw_assert(size_mul_check(sz1, sz2)); |
151 | | |
152 | 168k | return tor_realloc(ptr, (sz1 * sz2)); |
153 | 168k | } |
154 | | |
155 | | /** Return a newly allocated copy of the NUL-terminated string s. On |
156 | | * error, log and terminate. (Like strdup(s), but never returns |
157 | | * NULL.) |
158 | | */ |
159 | | char * |
160 | | tor_strdup_(const char *s) |
161 | 7.96M | { |
162 | 7.96M | char *duplicate; |
163 | 7.96M | raw_assert(s); |
164 | | |
165 | 7.96M | duplicate = raw_strdup(s); |
166 | | |
167 | 7.96M | if (PREDICT_UNLIKELY(duplicate == NULL)) { |
168 | | /* LCOV_EXCL_START */ |
169 | 0 | raw_assert_unreached_msg("Out of memory on strdup(). Dying."); |
170 | | /* LCOV_EXCL_STOP */ |
171 | 0 | } |
172 | 7.96M | return duplicate; |
173 | 7.96M | } |
174 | | |
175 | | /** Allocate and return a new string containing the first <b>n</b> |
176 | | * characters of <b>s</b>. If <b>s</b> is longer than <b>n</b> |
177 | | * characters, only the first <b>n</b> are copied. The result is |
178 | | * always NUL-terminated. (Like strndup(s,n), but never returns |
179 | | * NULL.) |
180 | | */ |
181 | | char * |
182 | | tor_strndup_(const char *s, size_t n) |
183 | 12.7M | { |
184 | 12.7M | char *duplicate; |
185 | 12.7M | raw_assert(s); |
186 | 12.7M | raw_assert(n < SIZE_T_CEILING); |
187 | 12.7M | duplicate = tor_malloc_((n+1)); |
188 | | /* Performance note: Ordinarily we prefer strlcpy to strncpy. But |
189 | | * this function gets called a whole lot, and platform strncpy is |
190 | | * much faster than strlcpy when strlen(s) is much longer than n. |
191 | | */ |
192 | 12.7M | strncpy(duplicate, s, n); |
193 | 12.7M | duplicate[n]='\0'; |
194 | 12.7M | return duplicate; |
195 | 12.7M | } |
196 | | |
197 | | /** Allocate a chunk of <b>len</b> bytes, with the same contents as the |
198 | | * <b>len</b> bytes starting at <b>mem</b>. */ |
199 | | void * |
200 | | tor_memdup_(const void *mem, size_t len) |
201 | 101k | { |
202 | 101k | char *duplicate; |
203 | 101k | raw_assert(len < SIZE_T_CEILING); |
204 | 101k | raw_assert(mem); |
205 | 101k | duplicate = tor_malloc_(len); |
206 | 101k | memcpy(duplicate, mem, len); |
207 | 101k | return duplicate; |
208 | 101k | } |
209 | | |
210 | | /** As tor_memdup(), but add an extra 0 byte at the end of the resulting |
211 | | * memory. */ |
212 | | void * |
213 | | tor_memdup_nulterm_(const void *mem, size_t len) |
214 | 113k | { |
215 | 113k | char *duplicate; |
216 | 113k | raw_assert(len < SIZE_T_CEILING+1); |
217 | 113k | raw_assert(mem); |
218 | 113k | duplicate = tor_malloc_(len+1); |
219 | 113k | memcpy(duplicate, mem, len); |
220 | 113k | duplicate[len] = '\0'; |
221 | 113k | return duplicate; |
222 | 113k | } |
223 | | |
224 | | /** Helper for places that need to take a function pointer to the right |
225 | | * spelling of "free()". */ |
226 | | void |
227 | | tor_free_(void *mem) |
228 | 213M | { |
229 | 213M | tor_free(mem); |
230 | 213M | } |