1 /*
2 * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <limits.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <openssl/err.h>
15 #include <openssl/types.h>
16 #include "testutil.h"
17
18 #ifndef USE_CUSTOM_ALLOC_FNS
19 # define USE_CUSTOM_ALLOC_FNS 0
20 #endif
21
22 /* Change to 1 to see every call of the custom allocator functions */
23 #define CUSTOM_FN_PRINT_CALLS 0
24
25 enum exp_ret_flags { EXP_FAIL = 0x10 };
26
27 enum exp_ret {
28 /** Expecting success */
29 EXP_NONNULL,
30 /** Zero-size special case: can either return NULL or a special pointer */
31 EXP_ZERO_SIZE,
32 /** Expecting an error due to insufficient memory */
33 EXP_OOM = EXP_FAIL,
34 /** Expecting error due to invalid arguments */
35 EXP_INVAL,
36 /** Expecting error due to integer overflow */
37 EXP_INT_OF,
38 };
39
40 #define IS_FAIL(exp_) (!!((int) (exp) & (int) EXP_FAIL))
41
42 static const char test_fn[] = "test_file_name";
43 enum { test_line = 31415926 };
44
45 #define SQRT_SIZE_T ((size_t) 1 << (sizeof(size_t) * (CHAR_BIT / 2)))
46 #define SQSQRT_SIZE_T ((size_t) 1 << (sizeof(size_t) * (CHAR_BIT / 4)))
47
48 #define MIN(a, b) ((a) < (b) ? (a) : (b))
49
50 #if !defined(OPENSSL_NO_CRYPTO_MDEBUG) || USE_CUSTOM_ALLOC_FNS
51 struct call_counts {
52 int malloc;
53 int realloc;
54 int free;
55 };
56 #endif
57 #if !defined(OPENSSL_NO_CRYPTO_MDEBUG)
58 static struct call_counts mdebug_counts;
59 #endif
60 #if USE_CUSTOM_ALLOC_FNS
61 static struct call_counts saved_custom_counts, cur_custom_counts;
62 #endif
63
64 static const struct array_alloc_vector {
65 size_t nmemb;
66 size_t size;
67 enum exp_ret exp_malloc;
68 enum exp_ret exp_calloc;
69 } array_alloc_vectors[] = {
70 { 0, 0, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
71 { 0, 1, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
72 { 0, SQRT_SIZE_T - 1, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
73 { 0, SQRT_SIZE_T, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
74 { 0, SIZE_MAX, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
75 { 1, 0, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
76 { SQRT_SIZE_T - 1, 0, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
77 { SIZE_MAX, 0, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
78
79 { 1, 1, EXP_NONNULL, EXP_NONNULL },
80
81 { SQRT_SIZE_T / 2, SQRT_SIZE_T, EXP_OOM, EXP_OOM },
82
83 { SQRT_SIZE_T, SQRT_SIZE_T, EXP_ZERO_SIZE, EXP_INT_OF },
84
85 /* Some magic numbers */
86 #if SIZE_MAX == 4294967295U
87 { 641, 6700417, EXP_NONNULL, EXP_INT_OF },
88 #else /* Of course there are no archutectures other than 32- and 64-bit ones */
89 { 274177, 67280421310721LLU, EXP_NONNULL, EXP_INT_OF },
90 #endif
91
92 { SIZE_MAX / 4 * 3, SIZE_MAX / 2, EXP_OOM, EXP_INT_OF },
93 };
94
95 static const struct array_realloc_vector {
96 size_t size;
97 size_t orig_nmemb;
98 size_t new_nmemb;
99 enum exp_ret exp_orig;
100 enum exp_ret exp_new;
101 enum exp_ret exp_orig_array;
102 enum exp_ret exp_new_array;
103 } array_realloc_vectors[] = {
104 { 0, 0, 0,
105 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
106 { 0, 0, 1,
107 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
108 { 0, 0, SIZE_MAX,
109 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
110 { 0, 1, 0,
111 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
112 { 0, SIZE_MAX, 0,
113 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
114 { 0, 1, SIZE_MAX,
115 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
116 { 0, SIZE_MAX, 1,
117 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
118 { 0, SIZE_MAX, SIZE_MAX,
119 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
120
121 { 1, 0, 0,
122 EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
123 { 1, 0, 1,
124 EXP_ZERO_SIZE, EXP_NONNULL, EXP_ZERO_SIZE, EXP_NONNULL },
125 { 1, 0, SIZE_MAX,
126 EXP_ZERO_SIZE, EXP_OOM, EXP_ZERO_SIZE, EXP_OOM },
127 { 1, 1, 0,
128 EXP_NONNULL, EXP_ZERO_SIZE, EXP_NONNULL, EXP_ZERO_SIZE },
129 { 1, SIZE_MAX, 0,
130 EXP_OOM, EXP_ZERO_SIZE, EXP_OOM, EXP_ZERO_SIZE },
131
132 { 1, 123, 345,
133 EXP_NONNULL, EXP_NONNULL, EXP_NONNULL, EXP_NONNULL },
134 { 1, 345, 123,
135 EXP_NONNULL, EXP_NONNULL, EXP_NONNULL, EXP_NONNULL },
136 { 12, 34, 56,
137 EXP_NONNULL, EXP_NONNULL, EXP_NONNULL, EXP_NONNULL },
138 { 12, 56, 34,
139 EXP_NONNULL, EXP_NONNULL, EXP_NONNULL, EXP_NONNULL },
140
141 { SQSQRT_SIZE_T, SIZE_MAX / SQSQRT_SIZE_T + 1, SIZE_MAX / SQSQRT_SIZE_T + 2,
142 EXP_ZERO_SIZE, EXP_NONNULL, EXP_INT_OF, EXP_INT_OF },
143 { SQSQRT_SIZE_T, SIZE_MAX / SQSQRT_SIZE_T + 2, SIZE_MAX / SQSQRT_SIZE_T + 1,
144 EXP_NONNULL, EXP_ZERO_SIZE, EXP_INT_OF, EXP_INT_OF },
145
146 { 123, 12, SIZE_MAX / 123 + 12,
147 EXP_NONNULL, EXP_NONNULL, EXP_NONNULL, EXP_INT_OF },
148 { 123, SIZE_MAX / 123 + 12, 12,
149 EXP_NONNULL, EXP_NONNULL, EXP_INT_OF, EXP_NONNULL },
150 };
151
152 static const struct array_aligned_alloc_vector {
153 size_t nmemb;
154 size_t size;
155 size_t align;
156 enum exp_ret exp;
157 enum exp_ret exp_array;
158 } array_aligned_alloc_vectors[] = {
159 { 0, 0, 0, EXP_INVAL, EXP_INVAL },
160 { 0, 0, 1, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
161 { 0, 0, 2, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
162 { 0, 0, 3, EXP_INVAL, EXP_INVAL },
163 { 0, 0, 4, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
164 { 0, 0, 64, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
165 { 0, 0, SQSQRT_SIZE_T, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
166 /*
167 * This one gets mem_alloc_custom_fns_test killed with SIGKILL
168 * on the linux-arm64 github runner.
169 */
170 /* { 0, 0, SQRT_SIZE_T, EXP_ZERO_SIZE, EXP_ZERO_SIZE }, */
171
172 { 0, 0, 64, EXP_ZERO_SIZE, EXP_ZERO_SIZE },
173
174 { 8, 8, 63, EXP_INVAL, EXP_INVAL },
175 { 8, 8, 64, EXP_NONNULL, EXP_NONNULL },
176 { SIZE_MAX / 8 + 9, 8, 64, EXP_NONNULL, EXP_INT_OF },
177
178 /*
179 * posix_memalign expected to fail with ENOMEM, while the open-coded
180 * implementation tries to alloc size + alignment, which should fail
181 * on integer overflow.
182 */
183 { 1, SIZE_MAX / 2 + 2, SIZE_MAX / 2 + 1,
184 #if (defined(_BSD_SOURCE) \
185 || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)) \
186 && !USE_CUSTOM_ALLOC_FNS || defined(OPENSSL_SMALL_FOOTPRINT)
187 EXP_OOM, EXP_OOM
188 #else
189 EXP_INT_OF, EXP_INT_OF
190 #endif
191 },
192 };
193
194 static int secure_memory_is_secure;
195
196 #if USE_CUSTOM_ALLOC_FNS
my_malloc(const size_t num,const char * const file,const int line)197 static void *my_malloc(const size_t num,
198 const char * const file, const int line)
199 {
200 void * const p = malloc(num);
201
202 # if CUSTOM_FN_PRINT_CALLS
203 if (file == test_fn || file == NULL
204 || (strcmp(file, OPENSSL_FILE) == 0 && file[0] != '\0'))
205 TEST_note("[%s:%d]: malloc(%#zx) -> %p", file, line, num, p);
206 # endif
207
208 if (cur_custom_counts.malloc < INT_MAX)
209 cur_custom_counts.malloc++;
210
211 return p;
212 }
my_realloc(void * const addr,const size_t num,const char * const file,const int line)213 static void *my_realloc(void * const addr, const size_t num,
214 const char * const file, const int line)
215 {
216 # if CUSTOM_FN_PRINT_CALLS
217 const uintptr_t old_addr = (uintptr_t) addr;
218 # endif
219 void * const p = realloc(addr, num);
220
221 # if CUSTOM_FN_PRINT_CALLS
222 if (file == test_fn || file == NULL
223 || (strcmp(file, OPENSSL_FILE) == 0 && file[0] != '\0'))
224 TEST_note("[%s:%d]: realloc(%#" PRIxPTR ", %#zx) -> %p",
225 file, line, old_addr, num, p);
226 # endif
227
228 if (cur_custom_counts.realloc < INT_MAX)
229 cur_custom_counts.realloc++;
230
231 return p;
232 }
233
my_free(void * const addr,const char * const file,const int line)234 static void my_free(void * const addr, const char * const file, const int line)
235 {
236 # if CUSTOM_FN_PRINT_CALLS
237 if (file == test_fn || file == NULL
238 || (strcmp(file, OPENSSL_FILE) == 0 && file[0] != '\0'))
239 TEST_note("[%s:%d]: free(%p)", file, line, addr);
240 # endif
241
242 if (cur_custom_counts.free < INT_MAX)
243 cur_custom_counts.free++;
244
245 free(addr);
246 }
247 #endif /* USE_CUSTOM_ALLOC_FNS */
248
check_zero_mem(char * p,size_t sz)249 static bool check_zero_mem(char *p, size_t sz)
250 {
251 for (size_t i = 0; i < sz; i++) {
252 if (p[i] != 0) {
253 TEST_error("Non-zero byte %zu of %zu (%#04hhx)", i, sz, p[i]);
254
255 return false;
256 }
257 }
258
259 return true;
260 }
261
save_counts(void)262 static void save_counts(void)
263 {
264 #if !defined(OPENSSL_NO_CRYPTO_MDEBUG)
265 CRYPTO_get_alloc_counts(&mdebug_counts.malloc,
266 &mdebug_counts.realloc,
267 &mdebug_counts.free);
268 #endif
269
270 #if USE_CUSTOM_ALLOC_FNS
271 saved_custom_counts = cur_custom_counts;
272 #endif
273 }
274
check_exp_prep(void)275 static void check_exp_prep(void)
276 {
277 ERR_set_mark();
278
279 save_counts();
280 }
281
282 /*
283 * Retrieve fresh call counts and check against the expected ones,
284 * when the latter are no less than zero.
285 */
check_counts(int exp_mallocs,int exp_reallocs,int exp_frees)286 static bool check_counts(int exp_mallocs, int exp_reallocs, int exp_frees)
287 {
288 int test_result = 1;
289
290 #if !defined(OPENSSL_NO_CRYPTO_MDEBUG)
291 {
292 struct call_counts cur;
293
294 CRYPTO_get_alloc_counts(&cur.malloc, &cur.realloc, &cur.free);
295 if (exp_mallocs >= 0
296 && !TEST_int_eq(cur.malloc - mdebug_counts.malloc, exp_mallocs))
297 test_result = 0;
298 if (exp_reallocs >= 0
299 && !TEST_int_eq(cur.realloc - mdebug_counts.realloc, exp_reallocs))
300 test_result = 0;
301 if (exp_frees >= 0
302 && !TEST_int_eq(cur.free - mdebug_counts.free, exp_frees))
303 test_result = 0;
304 }
305 #endif
306
307 #if USE_CUSTOM_ALLOC_FNS
308 if (exp_mallocs >= 0
309 && !TEST_int_eq(cur_custom_counts.malloc - saved_custom_counts.malloc,
310 exp_mallocs))
311 test_result = 0;
312 if (exp_reallocs >= 0
313 && !TEST_int_eq(cur_custom_counts.realloc - saved_custom_counts.realloc,
314 exp_reallocs))
315 test_result = 0;
316 if (exp_frees >= 0
317 && !TEST_int_eq(cur_custom_counts.free - saved_custom_counts.free,
318 exp_frees))
319 test_result = 0;
320 #endif
321
322 return test_result;
323 }
324
check_exp(const char * const fn,const int ln,const size_t sz,const bool secure,const bool zero,char * const ret,const enum exp_ret exp,int exp_mallocs,int exp_reallocs)325 static int check_exp(const char * const fn, const int ln, const size_t sz,
326 const bool secure, const bool zero, char * const ret,
327 const enum exp_ret exp, int exp_mallocs, int exp_reallocs)
328 {
329 int num_errs;
330 unsigned long err_code = 0;
331 const char *err_file = NULL;
332 int err_line = 0;
333 const char *err_func = NULL;
334 const char *err_data = NULL;
335 int err_flags = 0;
336 int test_result = 1;
337 unsigned long oom_err;
338
339 num_errs = ERR_count_to_mark();
340 if (num_errs > 0) {
341 err_code = ERR_peek_last_error_all(&err_file, &err_line, &err_func,
342 &err_data, &err_flags);
343 }
344
345 switch (exp) {
346 case EXP_OOM:
347 oom_err = secure ? CRYPTO_R_SECURE_MALLOC_FAILURE
348 : ERR_R_MALLOC_FAILURE;
349 if (!TEST_ptr_null(ret)
350 || !TEST_int_eq(num_errs, 1)
351 || !TEST_ulong_eq(err_code, ERR_PACK(ERR_LIB_CRYPTO, 0, oom_err))
352 || !TEST_str_eq(err_file, fn)
353 || !TEST_int_eq(err_line, ln)
354 || !TEST_str_eq(err_func, "")
355 || !TEST_str_eq(err_data, "")
356 || !TEST_int_eq(err_flags, 0))
357 test_result = 0;
358
359 break;
360
361 case EXP_INVAL:
362 if (!TEST_ptr_null(ret)
363 || !TEST_int_eq(num_errs, 1)
364 || !TEST_ulong_eq(err_code, ERR_PACK(ERR_LIB_CRYPTO, 0,
365 ERR_R_PASSED_INVALID_ARGUMENT))
366 || !TEST_str_eq(err_file, fn)
367 || !TEST_int_eq(err_line, ln)
368 || !TEST_str_eq(err_func, "")
369 || !TEST_str_eq(err_data, "")
370 || !TEST_int_eq(err_flags, 0))
371 test_result = 0;
372
373 break;
374
375 case EXP_INT_OF:
376 if (!TEST_ptr_null(ret)
377 || !TEST_int_eq(num_errs, 1)
378 || !TEST_ulong_eq(err_code, ERR_PACK(ERR_LIB_CRYPTO, 0,
379 CRYPTO_R_INTEGER_OVERFLOW))
380 || !TEST_str_eq(err_file, fn)
381 || !TEST_int_eq(err_line, ln)
382 || !TEST_str_eq(err_func, "")
383 || !TEST_str_eq(err_data, "")
384 || !TEST_int_eq(err_flags, 0))
385 test_result = 0;
386
387 break;
388
389 case EXP_NONNULL:
390 if (!TEST_ptr(ret)
391 || !TEST_int_eq(num_errs, 0)) {
392 test_result = 0;
393 } else if (zero) {
394 if (!check_zero_mem(ret, sz))
395 test_result = 0;
396 }
397
398 break;
399
400 case EXP_ZERO_SIZE:
401 /*
402 * Since the pointer ca either be NULL or non-NULL, depending
403 * on implementation, we can only check for the absence of errors.
404 */
405 if (!TEST_int_eq(num_errs, 0))
406 test_result = 0;
407
408 break;
409
410 default:
411 TEST_error("Unexpected expected result");
412 test_result = 0;
413 }
414
415 ERR_pop_to_mark();
416
417 /*
418 * We don't check for frees here as there's a non-trivial amount
419 * of free calls in the error handling routines.
420 */
421 test_result &= check_counts(exp_mallocs, exp_reallocs, -1);
422
423 return test_result;
424 }
425
test_xalloc(const bool secure,const bool array,const bool zero,const bool macro,const struct array_alloc_vector * td)426 static int test_xalloc(const bool secure, const bool array, const bool zero,
427 const bool macro, const struct array_alloc_vector *td)
428 {
429 char *ret;
430 int ln = test_line;
431 size_t sz = td->nmemb * td->size;
432 enum exp_ret exp = array ? td->exp_calloc : td->exp_malloc;
433 bool really_secure = secure && secure_memory_is_secure;
434 int exp_cnt = 0;
435 int res;
436
437 check_exp_prep();
438
439 if (macro) {
440 if (secure) {
441 if (array) {
442 if (zero)
443 ln = OPENSSL_LINE, ret = OPENSSL_secure_calloc(td->nmemb, td->size);
444 else
445 ln = OPENSSL_LINE, ret = OPENSSL_secure_malloc_array(td->nmemb, td->size);
446 } else {
447 if (zero)
448 ln = OPENSSL_LINE, ret = OPENSSL_secure_zalloc(sz);
449 else
450 ln = OPENSSL_LINE, ret = OPENSSL_secure_malloc(sz);
451 }
452 } else {
453 if (array) {
454 if (zero)
455 ln = OPENSSL_LINE, ret = OPENSSL_calloc(td->nmemb, td->size);
456 else
457 ln = OPENSSL_LINE, ret = OPENSSL_malloc_array(td->nmemb, td->size);
458 } else {
459 if (zero)
460 ln = OPENSSL_LINE, ret = OPENSSL_zalloc(sz);
461 else
462 ln = OPENSSL_LINE, ret = OPENSSL_malloc(sz);
463 }
464 }
465 } else {
466 if (array) {
467 ret = (secure ? (zero ? CRYPTO_secure_calloc
468 : CRYPTO_secure_malloc_array)
469 : (zero ? CRYPTO_calloc
470 : CRYPTO_malloc_array))(td->nmemb, td->size,
471 test_fn, test_line);
472 } else {
473 ret = (secure ? (zero ? CRYPTO_secure_zalloc
474 : CRYPTO_secure_malloc)
475 : (zero ? CRYPTO_zalloc
476 : CRYPTO_malloc))(sz, test_fn, test_line);
477 }
478 }
479
480 /*
481 * There is an OPENSSL_calloc in ERR_set_debug, triggered
482 * from ossl_report_alloc_err_ex.
483 */
484 exp_cnt += IS_FAIL(exp) && (!macro || (bool) OPENSSL_FILE[0]);
485 /*
486 * Secure allocations don't trigger alloc counting.
487 * EXP_OOM is special as it comes on return from the (called and counted)
488 * allocation function.
489 */
490 if (!really_secure)
491 exp_cnt += !!(exp == EXP_OOM || !IS_FAIL(exp));
492 res = check_exp(macro ? OPENSSL_FILE : test_fn, ln, sz, really_secure, zero,
493 ret, exp, exp_cnt, 0);
494
495 if (really_secure)
496 OPENSSL_secure_free(ret);
497 else
498 OPENSSL_free(ret);
499
500 return res;
501 }
502
test_xrealloc(const bool clear,const bool array,const bool macro,const struct array_realloc_vector * td)503 static int test_xrealloc(const bool clear, const bool array, const bool macro,
504 const struct array_realloc_vector *td)
505 {
506 char *ret = NULL;
507 char *old_ret = NULL;
508 int exp_malloc_cnt, exp_realloc_cnt;
509 int res = 1;
510 size_t i;
511
512 /*
513 * Do two passes, first with NULL ptr, then with the result of the first
514 * call.
515 */
516 for (i = 0; i < 2; i++) {
517 size_t nmemb = i ? td->new_nmemb : td->orig_nmemb;
518 size_t old_nmemb = i ? td->orig_nmemb : 0;
519 size_t sz = nmemb * td->size;
520 size_t old_sz = old_nmemb * td->size;
521 int ln = test_line;
522 enum exp_ret exp = i ? (array ? td->exp_new_array : td->exp_new)
523 : (array ? td->exp_orig_array : td->exp_orig);
524 enum exp_ret exp2 = !i ? (array ? td->exp_new_array : td->exp_new)
525 : (array ? td->exp_orig_array : td->exp_orig);
526
527 exp_malloc_cnt = exp_realloc_cnt = 0;
528
529 /* clear_realloc_array checks both new and old sizes */
530 if (clear && array && i && exp2 == EXP_INT_OF)
531 exp = EXP_INT_OF;
532
533 if (exp != EXP_INT_OF) {
534 if (clear) {
535 /*
536 * clear_alloc just calls cleanse if contraction has been
537 * requested.
538 */
539 if (ret == NULL || sz > old_sz)
540 exp_malloc_cnt++;
541 } else {
542 exp_realloc_cnt++;
543 #if !USE_CUSTOM_ALLOC_FNS
544 /* CRYPTO_malloc() is called explicitly when p is NULL. */
545 if (ret == NULL)
546 exp_malloc_cnt++;
547 #endif
548 }
549 } else {
550 if (!macro || OPENSSL_FILE[0] != '\0')
551 exp_malloc_cnt++;
552 }
553
554 check_exp_prep();
555
556 if (macro) {
557 if (array) {
558 if (clear)
559 ln = OPENSSL_LINE, ret = OPENSSL_clear_realloc_array(ret, old_nmemb, nmemb, td->size);
560 else
561 ln = OPENSSL_LINE, ret = OPENSSL_realloc_array(ret, nmemb, td->size);
562 } else {
563 if (clear)
564 ln = OPENSSL_LINE, ret = OPENSSL_clear_realloc(ret, old_sz, sz);
565 else
566 ln = OPENSSL_LINE, ret = OPENSSL_realloc(ret, sz);
567 }
568 } else {
569 if (array) {
570 if (clear)
571 ret = CRYPTO_clear_realloc_array(ret, old_nmemb, nmemb,
572 td->size,
573 test_fn, test_line);
574 else
575 ret = CRYPTO_realloc_array(ret, nmemb, td->size,
576 test_fn, test_line);
577 } else {
578 if (clear)
579 ret = CRYPTO_clear_realloc(ret, old_sz, sz,
580 test_fn, test_line);
581 else
582 ret = CRYPTO_realloc(ret, sz, test_fn, test_line);
583 }
584 }
585
586 /*
587 * There is an OPENSSL_calloc in ERR_set_debug, triggered
588 * from ossl_report_alloc_err_ex.
589 */
590 exp_malloc_cnt += !!(exp == EXP_OOM
591 && (!macro || (bool) OPENSSL_FILE[0]));
592
593 res = check_exp(macro ? OPENSSL_FILE : test_fn, ln, sz, false, false,
594 ret, exp, exp_malloc_cnt, exp_realloc_cnt);
595 if (res == 0)
596 TEST_error("realloc return code check fail with i = %zu, ret = %p"
597 ", old_nmemb = %#zx, nmemb = %#zx, size = %#zx",
598 i, (void *) ret, old_nmemb, nmemb, td->size);
599
600 /* Write data on the first pass and check it on the second */
601 if (res != 0 && exp == EXP_NONNULL && exp2 == EXP_NONNULL) {
602 size_t check_sz = MIN(td->orig_nmemb * td->size,
603 td->new_nmemb * td->size);
604 size_t j;
605 size_t num_err = 0;
606
607 if (i != 0) {
608 for (j = 0; j < check_sz; j++) {
609 char exp_val = (uint8_t) ((uintptr_t) td * 253 + j * 17);
610
611 if (ret[j] != exp_val) {
612 if (!num_err)
613 TEST_error("Memory mismatch at byte %zu of %zu: "
614 "%#04hhx != %#04hhx",
615 j, check_sz, ret[j], exp_val);
616
617 res = 0;
618 num_err++;
619 }
620 }
621
622 if (num_err != 0)
623 TEST_error("Total errors: %zu", num_err);
624 } else {
625 for (j = 0; j < check_sz; j++)
626 ret[j] = (uint8_t) ((uintptr_t) td * 253 + j * 17);
627 }
628 }
629
630 /* Freeing the old allocation if realloc has failed */
631 if (ret == NULL && exp != EXP_ZERO_SIZE)
632 OPENSSL_free(old_ret);
633
634 old_ret = ret;
635 }
636
637 OPENSSL_free(ret);
638
639 return res;
640 }
641
test_xaligned_alloc(const bool array,const bool macro,const struct array_aligned_alloc_vector * td)642 static int test_xaligned_alloc(const bool array, const bool macro,
643 const struct array_aligned_alloc_vector *td)
644 {
645 char *ret;
646 int ln = test_line;
647 size_t sz = td->nmemb * td->size;
648 enum exp_ret exp = array ? td->exp_array : td->exp;
649 int exp_cnt = 0;
650 void *freeptr = &freeptr;
651 int res = 1;
652
653 check_exp_prep();
654
655 if (macro) {
656 if (array) {
657 ln = OPENSSL_LINE, ret = OPENSSL_aligned_alloc_array(td->nmemb, td->size, td->align, &freeptr);
658 } else {
659 ln = OPENSSL_LINE, ret = OPENSSL_aligned_alloc(sz, td->align, &freeptr);
660 }
661 } else {
662 if (array)
663 ret = CRYPTO_aligned_alloc_array(td->nmemb, td->size, td->align,
664 &freeptr, test_fn, test_line);
665 else
666 ret = CRYPTO_aligned_alloc(sz, td->align, &freeptr,
667 test_fn, test_line);
668 }
669
670 #if !defined(OPENSSL_SMALL_FOOTPRINT)
671 /*
672 * aligned_alloc doesn't increment the call counts by itself, and
673 * OPENSSL_malloc is only called when the open-coded implementation
674 * is used.
675 */
676 # if USE_CUSTOM_ALLOC_FNS \
677 || !(defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L))
678 exp_cnt += !!(exp != EXP_INT_OF && exp != EXP_INVAL);
679 # endif
680 #else /* OPENSSL_SMALL_FOOTPRINT */
681 exp = exp == EXP_INT_OF ? EXP_INT_OF : EXP_ZERO_SIZE;
682 #endif /* !OPENSSL_SMALL_FOOTPRINT */
683
684 /*
685 * There is an OPENSSL_calloc in ERR_set_debug, triggered
686 * from ossl_report_alloc_err_ex.
687 */
688 exp_cnt += IS_FAIL(exp) && (!macro || (bool) OPENSSL_FILE[0]);
689 res &= check_exp(macro ? OPENSSL_FILE : test_fn, ln, sz, false, false,
690 ret, exp, exp_cnt, 0);
691
692 /* Check the pointer's alignment */
693 if (exp == EXP_NONNULL) {
694 if (!TEST_uint64_t_eq((uintptr_t) ret & (td->align - 1), 0))
695 res = 0;
696 }
697
698 #if !defined(OPENSSL_SMALL_FOOTPRINT)
699 if (IS_FAIL(exp) && !TEST_ptr_null(freeptr))
700 res = 0;
701 if ((exp == EXP_NONNULL) && !TEST_ptr(freeptr))
702 res = 0;
703 #else /* OPENSSL_SMALL_FOOTPRINT */
704 if (!TEST_ptr_null(ret) || !TEST_ptr_null(freeptr))
705 res = 0;
706 #endif /* !OPENSSL_SMALL_FOOTPRINT */
707
708 OPENSSL_free(freeptr);
709
710 return res;
711 }
712
test_malloc(const int i)713 static int test_malloc(const int i)
714 {
715 return test_xalloc(false, false, false, false, array_alloc_vectors + i)
716 && test_xalloc(false, false, false, true, array_alloc_vectors + i);
717 }
718
test_zalloc(const int i)719 static int test_zalloc(const int i)
720 {
721 return test_xalloc(false, false, true, false, array_alloc_vectors + i)
722 && test_xalloc(false, false, true, true, array_alloc_vectors + i);
723 }
724
test_malloc_array(const int i)725 static int test_malloc_array(const int i)
726 {
727 return test_xalloc(false, true, false, false, array_alloc_vectors + i)
728 && test_xalloc(false, true, false, true, array_alloc_vectors + i);
729 }
730
test_calloc(const int i)731 static int test_calloc(const int i)
732 {
733 return test_xalloc(false, true, true, false, array_alloc_vectors + i)
734 && test_xalloc(false, true, true, true, array_alloc_vectors + i);
735 }
736
test_secure_malloc(const int i)737 static int test_secure_malloc(const int i)
738 {
739 return test_xalloc(true, false, false, false, array_alloc_vectors + i)
740 && test_xalloc(true, false, false, true, array_alloc_vectors + i);
741 }
742
test_secure_zalloc(const int i)743 static int test_secure_zalloc(const int i)
744 {
745 return test_xalloc(true, false, true, false, array_alloc_vectors + i)
746 && test_xalloc(true, false, true, true, array_alloc_vectors + i);
747 }
748
test_secure_malloc_array(const int i)749 static int test_secure_malloc_array(const int i)
750 {
751 return test_xalloc(true, true, false, false, array_alloc_vectors + i)
752 && test_xalloc(true, true, false, true, array_alloc_vectors + i);
753 }
754
test_secure_calloc(const int i)755 static int test_secure_calloc(const int i)
756 {
757 return test_xalloc(true, true, true, false, array_alloc_vectors + i)
758 && test_xalloc(true, true, true, true, array_alloc_vectors + i);
759 }
760
test_realloc(const int i)761 static int test_realloc(const int i)
762 {
763 return test_xrealloc(false, false, false, array_realloc_vectors + i)
764 && test_xrealloc(false, false, true, array_realloc_vectors + i);
765 }
766
test_clear_realloc(const int i)767 static int test_clear_realloc(const int i)
768 {
769 return test_xrealloc(true, false, false, array_realloc_vectors + i)
770 && test_xrealloc(true, false, true, array_realloc_vectors + i);
771 }
772
test_realloc_array(const int i)773 static int test_realloc_array(const int i)
774 {
775 return test_xrealloc(false, true, false, array_realloc_vectors + i)
776 && test_xrealloc(false, true, true, array_realloc_vectors + i);
777 }
778
test_clear_realloc_array(const int i)779 static int test_clear_realloc_array(const int i)
780 {
781 return test_xrealloc(true, true, false, array_realloc_vectors + i)
782 && test_xrealloc(true, true, true, array_realloc_vectors + i);
783 }
784
test_aligned_alloc(const int i)785 static int test_aligned_alloc(const int i)
786 {
787 return test_xaligned_alloc(false, false, array_aligned_alloc_vectors + i)
788 && test_xaligned_alloc(false, true, array_aligned_alloc_vectors + i);
789 }
790
test_aligned_alloc_array(const int i)791 static int test_aligned_alloc_array(const int i)
792 {
793 return test_xaligned_alloc(true, false, array_aligned_alloc_vectors + i)
794 && test_xaligned_alloc(true, true, array_aligned_alloc_vectors + i);
795 }
796
test_free(void)797 static int test_free(void)
798 {
799 int test_result = 1;
800 void *p;
801
802 save_counts();
803 OPENSSL_free(NULL);
804 if (!TEST_int_eq(check_counts(0, 0, 1), 1))
805 test_result = 0;
806
807 save_counts();
808 CRYPTO_free(NULL, test_fn, test_line);
809 if (!TEST_int_eq(check_counts(0, 0, 1), 1))
810 test_result = 0;
811
812 save_counts();
813 p = OPENSSL_malloc(42);
814 OPENSSL_free(p);
815 if (!TEST_int_eq(check_counts(1, 0, 1), 1))
816 test_result = 0;
817
818 save_counts();
819 p = CRYPTO_calloc(23, 69, test_fn, test_line);
820 CRYPTO_free(p, test_fn, test_line);
821 if (!TEST_int_eq(check_counts(1, 0, 1), 1))
822 test_result = 0;
823
824 return test_result;
825 }
826
setup_tests(void)827 int setup_tests(void)
828 {
829 secure_memory_is_secure = CRYPTO_secure_malloc_init(65536, 4);
830 TEST_info("secure memory init: %d", secure_memory_is_secure);
831
832 ADD_ALL_TESTS(test_malloc, OSSL_NELEM(array_alloc_vectors));
833 ADD_ALL_TESTS(test_zalloc, OSSL_NELEM(array_alloc_vectors));
834 ADD_ALL_TESTS(test_malloc_array, OSSL_NELEM(array_alloc_vectors));
835 ADD_ALL_TESTS(test_calloc, OSSL_NELEM(array_alloc_vectors));
836
837 ADD_ALL_TESTS(test_secure_malloc, OSSL_NELEM(array_alloc_vectors));
838 ADD_ALL_TESTS(test_secure_zalloc, OSSL_NELEM(array_alloc_vectors));
839 ADD_ALL_TESTS(test_secure_malloc_array, OSSL_NELEM(array_alloc_vectors));
840 ADD_ALL_TESTS(test_secure_calloc, OSSL_NELEM(array_alloc_vectors));
841
842 ADD_ALL_TESTS(test_realloc, OSSL_NELEM(array_realloc_vectors));
843 ADD_ALL_TESTS(test_clear_realloc, OSSL_NELEM(array_realloc_vectors));
844 ADD_ALL_TESTS(test_realloc_array, OSSL_NELEM(array_realloc_vectors));
845 ADD_ALL_TESTS(test_clear_realloc_array, OSSL_NELEM(array_realloc_vectors));
846
847 ADD_ALL_TESTS(test_aligned_alloc, OSSL_NELEM(array_aligned_alloc_vectors));
848 ADD_ALL_TESTS(test_aligned_alloc_array,
849 OSSL_NELEM(array_aligned_alloc_vectors));
850
851 ADD_TEST(test_free);
852
853 return 1;
854 }
855
856 #if USE_CUSTOM_ALLOC_FNS
global_init(void)857 int global_init(void)
858 {
859 if (!CRYPTO_set_mem_functions(my_malloc, my_realloc, my_free)) {
860 fprintf(stderr, "Failed to override allocator functions");
861
862 return 0;
863 }
864
865 return 1;
866 }
867 #endif
868