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