Coverage Report

Created: 2024-06-28 06:19

/src/wolfssl/wolfcrypt/src/memory.c
Line
Count
Source (jump to first uncovered line)
1
/* memory.c
2
 *
3
 * Copyright (C) 2006-2023 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
23
#ifdef HAVE_CONFIG_H
24
    #include <config.h>
25
#endif
26
27
#ifdef WOLFSSL_LINUXKM
28
    /* inhibit "#undef current" in linuxkm_wc_port.h, included from wc_port.h,
29
     * because needed in linuxkm_memory.c, included below.
30
     */
31
    #define WOLFSSL_NEED_LINUX_CURRENT
32
#endif
33
34
#include <wolfssl/wolfcrypt/types.h>
35
36
/*
37
Possible memory options:
38
 * NO_WOLFSSL_MEMORY:               Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY.
39
 * WOLFSSL_STATIC_MEMORY:           Turns on the use of static memory buffers and functions.
40
                                        This allows for using static memory instead of dynamic.
41
 * WOLFSSL_STATIC_ALIGN:            Define defaults to 16 to indicate static memory alignment.
42
 * HAVE_IO_POOL:                    Enables use of static thread safe memory pool for input/output buffers.
43
 * XMALLOC_OVERRIDE:                Allows override of the XMALLOC, XFREE and XREALLOC macros.
44
 * XMALLOC_USER:                    Allows custom XMALLOC, XFREE and XREALLOC functions to be defined.
45
 * WOLFSSL_NO_MALLOC:               Disables the fall-back case to use STDIO malloc/free when no callbacks are set.
46
 * WOLFSSL_TRACK_MEMORY:            Enables memory tracking for total stats and list of allocated memory.
47
 * WOLFSSL_DEBUG_MEMORY:            Enables extra function and line number args for memory callbacks.
48
 * WOLFSSL_DEBUG_MEMORY_PRINT:      Enables printing of each malloc/free.
49
 * WOLFSSL_MALLOC_CHECK:            Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN
50
 * WOLFSSL_FORCE_MALLOC_FAIL_TEST:  Used for internal testing to induce random malloc failures.
51
 * WOLFSSL_HEAP_TEST:               Used for internal testing of heap hint
52
 * WOLFSSL_MEM_FAIL_COUNT:          Fail memory allocation at a count from
53
 *                                  environment variable: MEM_FAIL_CNT.
54
 */
55
56
#ifdef WOLFSSL_ZEPHYR
57
#undef realloc
58
void *z_realloc(void *ptr, size_t size)
59
{
60
    if (ptr == NULL)
61
        ptr = malloc(size);
62
    else
63
        ptr = realloc(ptr, size);
64
65
    return ptr;
66
}
67
#define realloc z_realloc
68
#endif
69
70
#ifdef USE_WOLFSSL_MEMORY
71
72
#include <wolfssl/wolfcrypt/memory.h>
73
#include <wolfssl/wolfcrypt/error-crypt.h>
74
#include <wolfssl/wolfcrypt/logging.h>
75
76
#if defined(WOLFSSL_DEBUG_MEMORY) && defined(WOLFSSL_DEBUG_MEMORY_PRINT)
77
#include <stdio.h>
78
#endif
79
80
#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
81
    static int gMemFailCountSeed;
82
    static int gMemFailCount;
83
    void wolfSSL_SetMemFailCount(int memFailCount)
84
    {
85
        if (gMemFailCountSeed == 0) {
86
            gMemFailCountSeed = memFailCount;
87
            gMemFailCount = memFailCount;
88
        }
89
    }
90
#endif
91
#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) || \
92
                                                     defined(WOLFSSL_MEMORY_LOG)
93
    #include <stdio.h>
94
#endif
95
96
97
/* Set these to default values initially. */
98
static wolfSSL_Malloc_cb  malloc_function = NULL;
99
static wolfSSL_Free_cb    free_function = NULL;
100
static wolfSSL_Realloc_cb realloc_function = NULL;
101
102
int wolfSSL_SetAllocators(wolfSSL_Malloc_cb  mf,
103
                          wolfSSL_Free_cb    ff,
104
                          wolfSSL_Realloc_cb rf)
105
2
{
106
2
    malloc_function = mf;
107
2
    free_function = ff;
108
2
    realloc_function = rf;
109
2
    return 0;
110
2
}
111
112
int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*  mf,
113
                          wolfSSL_Free_cb*    ff,
114
                          wolfSSL_Realloc_cb* rf)
115
0
{
116
0
    if (mf) *mf = malloc_function;
117
0
    if (ff) *ff = free_function;
118
0
    if (rf) *rf = realloc_function;
119
0
    return 0;
120
0
}
121
122
#ifdef WOLFSSL_MEM_FAIL_COUNT
123
static wolfSSL_Mutex memFailMutex;
124
int mem_fail_allocs = 0;
125
int mem_fail_frees = 0;
126
int mem_fail_cnt = 0;
127
128
void wc_MemFailCount_Init()
129
{
130
    char* cnt;
131
    wc_InitMutex(&memFailMutex);
132
    cnt = getenv("MEM_FAIL_CNT");
133
    if (cnt != NULL) {
134
        fprintf(stderr, "MemFailCount At: %d\n", mem_fail_cnt);
135
        mem_fail_cnt = atoi(cnt);
136
    }
137
}
138
static int wc_MemFailCount_AllocMem(void)
139
{
140
    int ret = 1;
141
142
    wc_LockMutex(&memFailMutex);
143
    if ((mem_fail_cnt > 0) && (mem_fail_cnt <= mem_fail_allocs + 1)) {
144
        ret = 0;
145
    }
146
    else {
147
        mem_fail_allocs++;
148
    }
149
    wc_UnLockMutex(&memFailMutex);
150
151
    return ret;
152
}
153
static void wc_MemFailCount_FreeMem(void)
154
{
155
    wc_LockMutex(&memFailMutex);
156
    mem_fail_frees++;
157
    wc_UnLockMutex(&memFailMutex);
158
}
159
void wc_MemFailCount_Free()
160
{
161
    wc_FreeMutex(&memFailMutex);
162
    fprintf(stderr, "MemFailCount Total: %d\n", mem_fail_allocs);
163
    fprintf(stderr, "MemFailCount Frees: %d\n", mem_fail_frees);
164
}
165
#endif
166
167
#ifndef WOLFSSL_STATIC_MEMORY
168
#ifdef WOLFSSL_CHECK_MEM_ZERO
169
170
#ifndef WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN
171
/* Number of entries in table of addresses to check. */
172
#define WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN    256
173
#endif
174
175
/* Alignment to maintain when adding length to allocated pointer.
176
 * Intel x64 wants to use aligned loads of XMM registers.
177
 */
178
#define MEM_ALIGN       16
179
180
/* An address that is meant to be all zeros for its length. */
181
typedef struct MemZero {
182
    /* Name of address to check. */
183
    const char* name;
184
    /* Address to check. */
185
    const void* addr;
186
    /* Length of data that must be zero. */
187
    size_t len;
188
} MemZero;
189
190
/* List of addresses to check. */
191
static MemZero memZero[WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN];
192
/* Next index to place address at.
193
 * -1 indicates uninitialized.
194
 * If nextIdx is equal to WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN then all entries
195
 * have been used.
196
 */
197
static int nextIdx = -1;
198
/* Mutex to protect modifying list of addresses to check. */
199
static wolfSSL_Mutex zeroMutex;
200
201
/* Initialize the table of addresses and the mutex.
202
 */
203
void wc_MemZero_Init()
204
{
205
    /* Clear the table to more easily see what is valid. */
206
    XMEMSET(memZero, 0, sizeof(memZero));
207
    /* Initialize mutex. */
208
    wc_InitMutex(&zeroMutex);
209
    /* Next index is first entry. */
210
    nextIdx = 0;
211
}
212
213
/* Free the mutex and check we have not any uncheck addresses.
214
 */
215
void wc_MemZero_Free()
216
{
217
    /* Free mutex. */
218
    wc_FreeMutex(&zeroMutex);
219
    /* Make sure we checked all addresses. */
220
    if (nextIdx > 0) {
221
        int i;
222
        fprintf(stderr, "[MEM_ZERO] Unseen: %d\n", nextIdx);
223
        for (i = 0; i < nextIdx; i++) {
224
            fprintf(stderr, "  %s - %p:%ld\n", memZero[i].name, memZero[i].addr,
225
                memZero[i].len);
226
        }
227
    }
228
    /* Uninitialized value in next index. */
229
    nextIdx = -1;
230
}
231
232
/* Add an address to check.
233
 *
234
 * @param [in] name  Name of address to check.
235
 * @param [in] addr  Address that needs to be checked.
236
 * @param [in] len   Length of data that must be zero.
237
 */
238
void wc_MemZero_Add(const char* name, const void* addr, size_t len)
239
{
240
    /* Initialize if not done. */
241
    if (nextIdx == -1) {
242
        wc_MemZero_Init();
243
    }
244
245
    /* Add an entry to the table while locked. */
246
    wc_LockMutex(&zeroMutex);
247
    if (nextIdx < WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN) {
248
        /* Fill in the next entry and update next index. */
249
        memZero[nextIdx].name = name;
250
        memZero[nextIdx].addr = addr;
251
        memZero[nextIdx].len  = len;
252
        nextIdx++;
253
    }
254
    else {
255
        /* Abort when too many entries. */
256
        fprintf(stderr, "\n[MEM_ZERO] Too many addresses to check\n");
257
        fprintf(stderr, "[MEM_ZERO] WOLFSSL_MEM_CHECK_ZERO_CACHE_LEN\n");
258
        abort();
259
    }
260
    wc_UnLockMutex(&zeroMutex);
261
}
262
263
/* Check the memory in the range of the address for memory that must be zero.
264
 *
265
 * @param [in] addr  Start address of memory that is to be checked.
266
 * @param [in] len   Length of data associated with address.
267
 */
268
void wc_MemZero_Check(void* addr, size_t len)
269
{
270
    int i;
271
    size_t j;
272
273
    wc_LockMutex(&zeroMutex);
274
    /* Look at each address for overlap with address passes in. */
275
    for (i = 0; i < nextIdx; i++) {
276
        if ((memZero[i].addr < addr) ||
277
               ((size_t)memZero[i].addr >= (size_t)addr + len)) {
278
            /* Check address not part of memory to check. */
279
            continue;
280
        }
281
282
        /* Address is in range of memory being freed - check each byte zero. */
283
        for (j = 0; j < memZero[i].len; j++) {
284
            if (((unsigned char*)memZero[i].addr)[j] != 0) {
285
                /* Byte not zero - abort! */
286
                fprintf(stderr, "\n[MEM_ZERO] %s:%p + %ld is not zero\n",
287
                    memZero[i].name, memZero[i].addr, j);
288
                fprintf(stderr, "[MEM_ZERO] Checking %p:%ld\n", addr, len);
289
                abort();
290
            }
291
        }
292
        /* Update next index to write to. */
293
        nextIdx--;
294
        if (nextIdx > 0) {
295
            /* Remove entry. */
296
            XMEMCPY(memZero + i, memZero + i + 1,
297
                sizeof(MemZero) * (nextIdx - i));
298
            /* Clear out top to make it easier to see what is to be checked. */
299
            XMEMSET(&memZero[nextIdx], 0, sizeof(MemZero));
300
        }
301
        /* Need to check this index again with new data. */
302
        i--;
303
    }
304
    wc_UnLockMutex(&zeroMutex);
305
}
306
#endif /* WOLFSSL_CHECK_MEM_ZERO */
307
308
#ifdef WOLFSSL_DEBUG_MEMORY
309
void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
310
#else
311
void* wolfSSL_Malloc(size_t size)
312
#endif
313
10.0M
{
314
10.0M
    void* res = 0;
315
316
#ifdef WOLFSSL_MEM_FAIL_COUNT
317
    if (!wc_MemFailCount_AllocMem()) {
318
        WOLFSSL_MSG("MemFailCnt: Fail malloc");
319
        return NULL;
320
    }
321
#endif
322
323
#ifdef WOLFSSL_CHECK_MEM_ZERO
324
    /* Space for requested size. */
325
    size += MEM_ALIGN;
326
#endif
327
328
10.0M
    if (malloc_function) {
329
    #ifdef WOLFSSL_DEBUG_MEMORY
330
        res = malloc_function(size, func, line);
331
    #else
332
10.0M
        res = malloc_function(size);
333
10.0M
    #endif
334
10.0M
    }
335
260
    else {
336
260
    #ifndef WOLFSSL_NO_MALLOC
337
        #ifdef WOLFSSL_TRAP_MALLOC_SZ
338
        if (size > WOLFSSL_TRAP_MALLOC_SZ) {
339
            WOLFSSL_MSG("Malloc too big!");
340
            return NULL;
341
        }
342
        #endif
343
344
260
        res = malloc(size);
345
    #else
346
        WOLFSSL_MSG("No malloc available");
347
    #endif
348
260
    }
349
350
#ifdef WOLFSSL_CHECK_MEM_ZERO
351
    /* Restore size to requested value. */
352
    size -= MEM_ALIGN;
353
    if (res != NULL) {
354
        /* Place size at front of allocated data and move pointer passed it. */
355
        *(size_t*)res = size;
356
        res = ((unsigned char*)res) + MEM_ALIGN;
357
    }
358
#endif
359
360
#ifdef WOLFSSL_DEBUG_MEMORY
361
#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
362
    fprintf(stderr, "Alloc: %p -> %u at %s:%u\n", res, (word32)size, func, line);
363
#else
364
    (void)func;
365
    (void)line;
366
#endif
367
#endif
368
369
#ifdef WOLFSSL_MALLOC_CHECK
370
    if (res == NULL)
371
        WOLFSSL_MSG("wolfSSL_malloc failed");
372
#endif
373
374
#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
375
    if (res && --gMemFailCount == 0) {
376
        fprintf(stderr, "\n---FORCED MEM FAIL TEST---\n");
377
        if (free_function) {
378
        #ifdef WOLFSSL_DEBUG_MEMORY
379
            free_function(res, func, line);
380
        #else
381
            free_function(res);
382
        #endif
383
        }
384
        else {
385
            free(res); /* clear */
386
        }
387
        gMemFailCount = gMemFailCountSeed; /* reset */
388
        return NULL;
389
    }
390
#endif
391
392
10.0M
    return res;
393
10.0M
}
394
395
#ifdef WOLFSSL_DEBUG_MEMORY
396
void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
397
#else
398
void wolfSSL_Free(void *ptr)
399
#endif
400
10.0M
{
401
#ifdef WOLFSSL_DEBUG_MEMORY
402
#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
403
    fprintf(stderr, "Free: %p at %s:%u\n", ptr, func, line);
404
#else
405
    (void)func;
406
    (void)line;
407
#endif
408
#endif
409
410
#ifdef WOLFSSL_CHECK_MEM_ZERO
411
    /* Move pointer back to originally allocated pointer. */
412
    ptr = ((unsigned char*)ptr) - MEM_ALIGN;
413
    /* Check that the pointer is zero where required. */
414
    wc_MemZero_Check(((unsigned char*)ptr) + MEM_ALIGN, *(size_t*)ptr);
415
#endif
416
#ifdef WOLFSSL_MEM_FAIL_COUNT
417
    wc_MemFailCount_FreeMem();
418
#endif
419
420
10.0M
    if (free_function) {
421
    #ifdef WOLFSSL_DEBUG_MEMORY
422
        free_function(ptr, func, line);
423
    #else
424
10.0M
        free_function(ptr);
425
10.0M
    #endif
426
10.0M
    }
427
256
    else {
428
256
    #ifndef WOLFSSL_NO_MALLOC
429
256
        free(ptr);
430
    #else
431
        WOLFSSL_MSG("No free available");
432
    #endif
433
256
    }
434
10.0M
}
435
436
#ifdef WOLFSSL_DEBUG_MEMORY
437
void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
438
#else
439
void* wolfSSL_Realloc(void *ptr, size_t size)
440
#endif
441
0
{
442
#ifdef WOLFSSL_CHECK_MEM_ZERO
443
    /* Can't check data that has been freed during realloc.
444
     * Manually allocated new memory, copy data and free original pointer.
445
     */
446
#ifdef WOLFSSL_DEBUG_MEMORY
447
    void* res = wolfSSL_Malloc(size, func, line);
448
#else
449
    void* res = wolfSSL_Malloc(size);
450
#endif
451
    if (ptr != NULL) {
452
        /* Copy the minimum of old and new size. */
453
        size_t copySize = *(size_t*)(((unsigned char*)ptr) - MEM_ALIGN);
454
        if (size < copySize) {
455
            copySize = size;
456
        }
457
        XMEMCPY(res, ptr, copySize);
458
        /* Dispose of old pointer. */
459
    #ifdef WOLFSSL_DEBUG_MEMORY
460
        wolfSSL_Free(ptr, func, line);
461
    #else
462
        wolfSSL_Free(ptr);
463
    #endif
464
    }
465
466
    /* Return new pointer with data copied into it. */
467
    return res;
468
#else
469
0
    void* res = 0;
470
471
#ifdef WOLFSSL_MEM_FAIL_COUNT
472
    if (!wc_MemFailCount_AllocMem()) {
473
        WOLFSSL_MSG("MemFailCnt: Fail realloc");
474
        return NULL;
475
    }
476
#endif
477
478
0
    if (realloc_function) {
479
    #ifdef WOLFSSL_DEBUG_MEMORY
480
        res = realloc_function(ptr, size, func, line);
481
    #else
482
0
        res = realloc_function(ptr, size);
483
0
    #endif
484
0
    }
485
0
    else {
486
0
    #ifndef WOLFSSL_NO_MALLOC
487
0
        res = realloc(ptr, size);
488
    #else
489
        WOLFSSL_MSG("No realloc available");
490
    #endif
491
0
    }
492
493
#ifdef WOLFSSL_MEM_FAIL_COUNT
494
    if (ptr != NULL) {
495
        wc_MemFailCount_FreeMem();
496
    }
497
#endif
498
499
0
    return res;
500
0
#endif
501
0
}
502
#endif /* WOLFSSL_STATIC_MEMORY */
503
504
#ifdef WOLFSSL_STATIC_MEMORY
505
506
struct wc_Memory {
507
    byte*  buffer;
508
    struct wc_Memory* next;
509
    word32 sz;
510
};
511
512
513
/* returns amount of memory used on success. On error returns negative value
514
   wc_Memory** list is the list that new buckets are prepended to
515
 */
516
static int create_memory_buckets(byte* buffer, word32 bufSz,
517
                              word32 buckSz, word32 buckNum, wc_Memory** list) {
518
    word32 i;
519
    byte*  pt  = buffer;
520
    int    ret = 0;
521
    word32 memSz = (word32)sizeof(wc_Memory);
522
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
523
524
    /* if not enough space available for bucket size then do not try */
525
    if (buckSz + memSz + padSz > bufSz) {
526
        return ret;
527
    }
528
529
    for (i = 0; i < buckNum; i++) {
530
        if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
531
            /* create a new struct and set its values */
532
            wc_Memory* mem = (struct wc_Memory*)(pt);
533
            mem->sz = buckSz;
534
            mem->buffer = (byte*)pt + padSz + memSz;
535
            mem->next = NULL;
536
537
            /* add the newly created struct to front of list */
538
            if (*list == NULL) {
539
                *list = mem;
540
            } else {
541
                mem->next = *list;
542
                *list = mem;
543
            }
544
545
            /* advance pointer and keep track of memory used */
546
            ret += buckSz + padSz + memSz;
547
            pt  += buckSz + padSz + memSz;
548
        }
549
        else {
550
            break; /* not enough space left for more buckets of this size */
551
        }
552
    }
553
554
    return ret;
555
}
556
557
int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap)
558
{
559
    word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
560
    word32 wc_Dist[WOLFMEM_DEF_BUCKETS]  = { WOLFMEM_DIST };
561
562
    if (heap == NULL) {
563
        return BAD_FUNC_ARG;
564
    }
565
566
    XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
567
568
    XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz));
569
    XMEMCPY(heap->distList, wc_Dist,  sizeof(wc_Dist));
570
571
    if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
572
        WOLFSSL_MSG("Error creating heap memory mutex");
573
        return BAD_MUTEX_E;
574
    }
575
576
    return 0;
577
}
578
579
int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
580
    unsigned char* buf, unsigned int sz, int flag, int maxSz)
581
{
582
    int ret;
583
    WOLFSSL_HEAP*      heap;
584
    WOLFSSL_HEAP_HINT* hint;
585
    word32 idx = 0;
586
587
    if (pHint == NULL || buf == NULL) {
588
        return BAD_FUNC_ARG;
589
    }
590
591
    if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
592
        return BUFFER_E; /* not enough memory for structures */
593
    }
594
595
    /* check if hint has already been assigned */
596
    if (*pHint == NULL) {
597
        heap = (WOLFSSL_HEAP*)buf;
598
        idx += sizeof(WOLFSSL_HEAP);
599
        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
600
        idx += sizeof(WOLFSSL_HEAP_HINT);
601
602
        ret = wolfSSL_init_memory_heap(heap);
603
        if (ret != 0) {
604
            return ret;
605
        }
606
607
        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
608
        hint->memory = heap;
609
    }
610
    else {
611
    #ifdef WOLFSSL_HEAP_TEST
612
        /* do not load in memory if test has been set */
613
        if (heap == (void*)WOLFSSL_HEAP_TEST) {
614
            return 0;
615
        }
616
    #endif
617
618
        hint = (WOLFSSL_HEAP_HINT*)(*pHint);
619
        heap = hint->memory;
620
    }
621
622
    ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap);
623
    if (ret != 1) {
624
        WOLFSSL_MSG("Error partitioning memory");
625
        return -1;
626
    }
627
628
    /* determine what max applies too */
629
    if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
630
        heap->maxIO = maxSz;
631
    }
632
    else { /* general memory used in handshakes */
633
        heap->maxHa = maxSz;
634
    }
635
636
    heap->flag |= flag;
637
    *pHint = hint;
638
639
    (void)maxSz;
640
641
    return 0;
642
}
643
644
int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
645
                                                             WOLFSSL_HEAP* heap)
646
{
647
    word32 ava = sz;
648
    byte*  pt  = buffer;
649
    int    ret = 0;
650
    word32 memSz = (word32)sizeof(wc_Memory);
651
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
652
653
    WOLFSSL_ENTER("wolfSSL_load_static_memory");
654
655
    if (buffer == NULL) {
656
        return BAD_FUNC_ARG;
657
    }
658
659
    /* align pt */
660
    while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
661
        *pt = 0x00;
662
        pt++;
663
        ava--;
664
    }
665
666
#ifdef WOLFSSL_DEBUG_MEMORY
667
    fprintf(stderr, "Allocated %d bytes for static memory @ %p\n", ava, pt);
668
#endif
669
670
    /* divide into chunks of memory and add them to available list */
671
    while (ava >= (heap->sizeList[0] + padSz + memSz)) {
672
        /* creating only IO buffers from memory passed in, max TLS is 16k */
673
        if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
674
            if ((ret = create_memory_buckets(pt, ava,
675
                                          WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
676
                WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
677
                return ret;
678
            }
679
680
            /* check if no more room left for creating IO buffers */
681
            if (ret == 0) {
682
                break;
683
            }
684
685
            /* advance pointer in buffer for next buckets and keep track
686
               of how much memory is left available */
687
            pt  += ret;
688
            ava -= ret;
689
        }
690
        else {
691
            int i;
692
            /* start at largest and move to smaller buckets */
693
            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
694
                if ((heap->sizeList[i] + padSz + memSz) <= ava) {
695
                    if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
696
                                     heap->distList[i], &(heap->ava[i]))) < 0) {
697
                        WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
698
                        return ret;
699
                    }
700
701
                    /* advance pointer in buffer for next buckets and keep track
702
                       of how much memory is left available */
703
                    pt  += ret;
704
                    ava -= ret;
705
                }
706
            }
707
        }
708
    }
709
710
    return 1;
711
}
712
713
714
/* returns the size of management memory needed for each bucket.
715
 * This is memory that is used to keep track of and align memory buckets. */
716
int wolfSSL_MemoryPaddingSz(void)
717
{
718
    word32 memSz = (word32)sizeof(wc_Memory);
719
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
720
    return memSz + padSz;
721
}
722
723
724
/* Used to calculate memory size for optimum use with buckets.
725
   returns the suggested size rounded down to the nearest bucket. */
726
int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
727
{
728
    word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS};
729
    word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST};
730
731
    word32 ava = sz;
732
    byte*  pt  = buffer;
733
    word32 memSz = (word32)sizeof(wc_Memory);
734
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
735
736
    WOLFSSL_ENTER("wolfSSL_static_size");
737
738
    if (buffer == NULL) {
739
        return BAD_FUNC_ARG;
740
    }
741
742
    /* align pt */
743
    while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
744
        pt++;
745
        ava--;
746
    }
747
748
    /* creating only IO buffers from memory passed in, max TLS is 16k */
749
    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
750
        if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
751
            return 0; /* not enough room for even one bucket */
752
        }
753
754
        ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
755
    }
756
    else {
757
        int i, k;
758
759
        if (ava < (bucketSz[0] + padSz + memSz)) {
760
            return 0; /* not enough room for even one bucket */
761
        }
762
763
        while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) {
764
            /* start at largest and move to smaller buckets */
765
            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
766
                for (k = distList[i]; k > 0; k--) {
767
                    if ((bucketSz[i] + padSz + memSz) <= ava) {
768
                        ava -= bucketSz[i] + padSz + memSz;
769
                    }
770
                }
771
            }
772
        }
773
    }
774
775
    return sz - ava; /* round down */
776
}
777
778
779
int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
780
{
781
    WOLFSSL_MSG("Freeing fixed IO buffer");
782
783
    /* check if fixed buffer was set */
784
    if (*io == NULL) {
785
        return 1;
786
    }
787
788
    if (heap == NULL) {
789
        WOLFSSL_MSG("No heap to return fixed IO too");
790
    }
791
    else {
792
        /* put IO buffer back into IO pool */
793
        (*io)->next = heap->io;
794
        heap->io    = *io;
795
        *io         = NULL;
796
    }
797
798
    return 1;
799
}
800
801
802
int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
803
{
804
    WOLFSSL_MSG("Setting fixed IO for SSL");
805
    if (heap == NULL) {
806
        return MEMORY_E;
807
    }
808
809
    *io = heap->io;
810
811
    if (*io != NULL) {
812
        heap->io = (*io)->next;
813
        (*io)->next = NULL;
814
    }
815
    else { /* failed to grab an IO buffer */
816
        return 0;
817
    }
818
819
    return 1;
820
}
821
822
823
int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
824
{
825
        word32     i;
826
        wc_Memory* pt;
827
828
        XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
829
830
        stats->totalAlloc = heap->alloc;
831
        stats->totalFr    = heap->frAlc;
832
        stats->curAlloc   = stats->totalAlloc - stats->totalFr;
833
        stats->maxHa      = heap->maxHa;
834
        stats->maxIO      = heap->maxIO;
835
        for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
836
            stats->blockSz[i] = heap->sizeList[i];
837
            for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
838
                stats->avaBlock[i] += 1;
839
            }
840
        }
841
842
        for (pt = heap->io; pt != NULL; pt = pt->next) {
843
            stats->avaIO++;
844
        }
845
846
        stats->flag       = heap->flag; /* flag used */
847
848
    return 1;
849
}
850
851
852
#ifdef WOLFSSL_DEBUG_MEMORY
853
void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
854
#else
855
void* wolfSSL_Malloc(size_t size, void* heap, int type)
856
#endif
857
{
858
    void* res = 0;
859
    wc_Memory* pt = NULL;
860
    int   i;
861
862
    /* check for testing heap hint was set */
863
#ifdef WOLFSSL_HEAP_TEST
864
    if (heap == (void*)WOLFSSL_HEAP_TEST) {
865
        return malloc(size);
866
    }
867
#endif
868
869
    /* if no heap hint then use dynamic memory*/
870
    if (heap == NULL) {
871
        #ifdef WOLFSSL_HEAP_TEST
872
            /* allow using malloc for creating ctx and method */
873
            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
874
                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
875
                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method");
876
                res = malloc(size);
877
            }
878
            else {
879
                WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC");
880
                res = NULL;
881
            }
882
        #else
883
        #ifndef WOLFSSL_NO_MALLOC
884
            #ifdef FREERTOS
885
                res = pvPortMalloc(size);
886
            #elif defined(WOLFSSL_EMBOS)
887
                res = OS_HEAP_malloc(size);
888
            #else
889
                res = malloc(size);
890
            #endif
891
892
            #ifdef WOLFSSL_DEBUG_MEMORY
893
                fprintf(stderr, "Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line);
894
            #endif
895
        #else
896
            WOLFSSL_MSG("No heap hint found to use and no malloc");
897
            #ifdef WOLFSSL_DEBUG_MEMORY
898
            fprintf(stderr, "ERROR: at %s:%d\n", func, line);
899
            #endif
900
        #endif /* WOLFSSL_NO_MALLOC */
901
        #endif /* WOLFSSL_HEAP_TEST */
902
    }
903
    else {
904
        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
905
        WOLFSSL_HEAP*      mem  = hint->memory;
906
907
        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
908
            WOLFSSL_MSG("Bad memory_mutex lock");
909
            return NULL;
910
        }
911
912
        /* case of using fixed IO buffers */
913
        if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
914
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
915
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
916
            if (type == DYNAMIC_TYPE_OUT_BUFFER) {
917
                pt = hint->outBuf;
918
            }
919
            if (type == DYNAMIC_TYPE_IN_BUFFER) {
920
                pt = hint->inBuf;
921
            }
922
        }
923
        else {
924
            /* check if using IO pool flag */
925
            if (mem->flag & WOLFMEM_IO_POOL &&
926
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
927
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
928
                if (mem->io != NULL) {
929
                    pt      = mem->io;
930
                    mem->io = pt->next;
931
                }
932
            }
933
934
            /* general static memory */
935
            if (pt == NULL) {
936
                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
937
                    if ((word32)size <= mem->sizeList[i]) {
938
                        if (mem->ava[i] != NULL) {
939
                            pt = mem->ava[i];
940
                            mem->ava[i] = pt->next;
941
                            break;
942
                        }
943
                    #ifdef WOLFSSL_DEBUG_STATIC_MEMORY
944
                        else {
945
                            fprintf(stderr, "Size: %ld, Empty: %d\n", size,
946
                                                              mem->sizeList[i]);
947
                        }
948
                    #endif
949
                    }
950
                }
951
            }
952
        }
953
954
        if (pt != NULL) {
955
            mem->inUse += pt->sz;
956
            mem->alloc += 1;
957
            res = pt->buffer;
958
959
        #ifdef WOLFSSL_DEBUG_MEMORY
960
            fprintf(stderr, "Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
961
        #endif
962
963
            /* keep track of connection statistics if flag is set */
964
            if (mem->flag & WOLFMEM_TRACK_STATS) {
965
                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
966
                if (stats != NULL) {
967
                    stats->curMem += pt->sz;
968
                    if (stats->peakMem < stats->curMem) {
969
                        stats->peakMem = stats->curMem;
970
                    }
971
                    stats->curAlloc++;
972
                    if (stats->peakAlloc < stats->curAlloc) {
973
                        stats->peakAlloc = stats->curAlloc;
974
                    }
975
                    stats->totalAlloc++;
976
                }
977
            }
978
        }
979
        else {
980
            WOLFSSL_MSG("ERROR ran out of static memory");
981
            #ifdef WOLFSSL_DEBUG_MEMORY
982
            fprintf(stderr, "Looking for %lu bytes at %s:%d\n", size, func, line);
983
            #endif
984
        }
985
986
        wc_UnLockMutex(&(mem->memory_mutex));
987
    }
988
989
    #ifdef WOLFSSL_MALLOC_CHECK
990
        if ((wc_ptr_t)res % WOLFSSL_STATIC_ALIGN) {
991
            WOLFSSL_MSG("ERROR memory is not aligned");
992
            res = NULL;
993
        }
994
    #endif
995
996
997
    (void)i;
998
    (void)pt;
999
    (void)type;
1000
1001
    return res;
1002
}
1003
1004
1005
#ifdef WOLFSSL_DEBUG_MEMORY
1006
void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
1007
#else
1008
void wolfSSL_Free(void *ptr, void* heap, int type)
1009
#endif
1010
{
1011
    int i;
1012
    wc_Memory* pt;
1013
1014
    if (ptr) {
1015
        /* check for testing heap hint was set */
1016
    #ifdef WOLFSSL_HEAP_TEST
1017
        if (heap == (void*)WOLFSSL_HEAP_TEST) {
1018
        #ifdef WOLFSSL_DEBUG_MEMORY
1019
            fprintf(stderr, "Free: %p at %s:%d\n", pt, func, line);
1020
        #endif
1021
            return free(ptr);
1022
        }
1023
    #endif
1024
1025
        if (heap == NULL) {
1026
        #ifdef WOLFSSL_HEAP_TEST
1027
            /* allow using malloc for creating ctx and method */
1028
            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
1029
                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
1030
                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method");
1031
            }
1032
            else {
1033
                WOLFSSL_MSG("ERROR null heap hint passed into XFREE");
1034
            }
1035
        #endif
1036
        #ifndef WOLFSSL_NO_MALLOC
1037
            #ifdef FREERTOS
1038
                vPortFree(ptr);
1039
            #elif defined(WOLFSSL_EMBOS)
1040
                OS_HEAP_free(ptr);
1041
            #else
1042
                free(ptr);
1043
            #endif
1044
        #else
1045
            WOLFSSL_MSG("Error trying to call free when turned off");
1046
        #endif /* WOLFSSL_NO_MALLOC */
1047
        }
1048
        else {
1049
            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
1050
            WOLFSSL_HEAP*      mem  = hint->memory;
1051
            word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
1052
1053
            /* get memory struct and add it to available list */
1054
            pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
1055
            if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1056
                WOLFSSL_MSG("Bad memory_mutex lock");
1057
                return;
1058
            }
1059
1060
            /* case of using fixed IO buffers */
1061
            if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
1062
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
1063
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1064
                /* fixed IO pools are free'd at the end of SSL lifetime
1065
                   using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
1066
            }
1067
            else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
1068
                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
1069
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1070
                pt->next = mem->io;
1071
                mem->io  = pt;
1072
            }
1073
            else { /* general memory free */
1074
                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
1075
                    if (pt->sz == mem->sizeList[i]) {
1076
                        pt->next = mem->ava[i];
1077
                        mem->ava[i] = pt;
1078
                        break;
1079
                    }
1080
                }
1081
            }
1082
            mem->inUse -= pt->sz;
1083
            mem->frAlc += 1;
1084
1085
        #ifdef WOLFSSL_DEBUG_MEMORY
1086
            fprintf(stderr, "Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
1087
        #endif
1088
1089
            /* keep track of connection statistics if flag is set */
1090
            if (mem->flag & WOLFMEM_TRACK_STATS) {
1091
                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
1092
                if (stats != NULL) {
1093
                    /* avoid under flow */
1094
                    if (stats->curMem > pt->sz) {
1095
                        stats->curMem -= pt->sz;
1096
                    }
1097
                    else {
1098
                        stats->curMem = 0;
1099
                    }
1100
1101
                    if (stats->curAlloc > 0) {
1102
                        stats->curAlloc--;
1103
                    }
1104
                    stats->totalFr++;
1105
                }
1106
            }
1107
            wc_UnLockMutex(&(mem->memory_mutex));
1108
        }
1109
    }
1110
1111
    (void)i;
1112
    (void)pt;
1113
    (void)type;
1114
}
1115
1116
#ifdef WOLFSSL_DEBUG_MEMORY
1117
void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
1118
#else
1119
void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
1120
#endif
1121
{
1122
    void* res = 0;
1123
    wc_Memory* pt = NULL;
1124
    int    i;
1125
1126
    /* check for testing heap hint was set */
1127
#ifdef WOLFSSL_HEAP_TEST
1128
    if (heap == (void*)WOLFSSL_HEAP_TEST) {
1129
        return realloc(ptr, size);
1130
    }
1131
#endif
1132
1133
    if (heap == NULL) {
1134
        #ifdef WOLFSSL_HEAP_TEST
1135
            WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC");
1136
        #endif
1137
        #ifndef WOLFSSL_NO_MALLOC
1138
            res = realloc(ptr, size);
1139
        #else
1140
            WOLFSSL_MSG("NO heap found to use for realloc");
1141
        #endif /* WOLFSSL_NO_MALLOC */
1142
    }
1143
    else {
1144
        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
1145
        WOLFSSL_HEAP*      mem  = hint->memory;
1146
        word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
1147
1148
        if (ptr == NULL) {
1149
        #ifdef WOLFSSL_DEBUG_MEMORY
1150
            return wolfSSL_Malloc(size, heap, type, func, line);
1151
        #else
1152
            return wolfSSL_Malloc(size, heap, type);
1153
        #endif
1154
        }
1155
1156
        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1157
            WOLFSSL_MSG("Bad memory_mutex lock");
1158
            return NULL;
1159
        }
1160
1161
        /* case of using fixed IO buffers or IO pool */
1162
        if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
1163
                                          && (type == DYNAMIC_TYPE_OUT_BUFFER ||
1164
                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
1165
            /* no realloc, is fixed size */
1166
            pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
1167
            if (pt->sz < size) {
1168
                WOLFSSL_MSG("Error IO memory was not large enough");
1169
                res = NULL; /* return NULL in error case */
1170
            }
1171
            res = pt->buffer;
1172
        }
1173
        else {
1174
        /* general memory */
1175
            for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
1176
                if ((word32)size <= mem->sizeList[i]) {
1177
                    if (mem->ava[i] != NULL) {
1178
                        pt = mem->ava[i];
1179
                        mem->ava[i] = pt->next;
1180
                        break;
1181
                    }
1182
                }
1183
            }
1184
1185
            if (pt != NULL && res == NULL) {
1186
                res = pt->buffer;
1187
1188
                /* copy over original information and free ptr */
1189
                word32 prvSz = ((wc_Memory*)((byte*)ptr - padSz -
1190
                                               sizeof(wc_Memory)))->sz;
1191
                prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
1192
                XMEMCPY(pt->buffer, ptr, prvSz);
1193
                mem->inUse += pt->sz;
1194
                mem->alloc += 1;
1195
1196
                /* free memory that was previously being used */
1197
                wc_UnLockMutex(&(mem->memory_mutex));
1198
                wolfSSL_Free(ptr, heap, type
1199
            #ifdef WOLFSSL_DEBUG_MEMORY
1200
                    , func, line
1201
            #endif
1202
                );
1203
                if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
1204
                    WOLFSSL_MSG("Bad memory_mutex lock");
1205
                    return NULL;
1206
                }
1207
            }
1208
        }
1209
        wc_UnLockMutex(&(mem->memory_mutex));
1210
    }
1211
1212
    #ifdef WOLFSSL_MALLOC_CHECK
1213
        if ((wc_ptr_t)res % WOLFSSL_STATIC_ALIGN) {
1214
            WOLFSSL_MSG("ERROR memory is not aligned");
1215
            res = NULL;
1216
        }
1217
    #endif
1218
1219
    (void)i;
1220
    (void)pt;
1221
    (void)type;
1222
1223
    return res;
1224
}
1225
#endif /* WOLFSSL_STATIC_MEMORY */
1226
1227
#endif /* USE_WOLFSSL_MEMORY */
1228
1229
1230
#ifdef HAVE_IO_POOL
1231
1232
/* Example for user io pool, shared build may need definitions in lib proper */
1233
1234
#include <stdlib.h>
1235
1236
#ifndef HAVE_THREAD_LS
1237
    #error "Oops, simple I/O pool example needs thread local storage"
1238
#endif
1239
1240
1241
/* allow simple per thread in and out pools */
1242
/* use 17k size since max record size is 16k plus overhead */
1243
static THREAD_LS_T byte pool_in[17*1024];
1244
static THREAD_LS_T byte pool_out[17*1024];
1245
1246
1247
void* XMALLOC(size_t n, void* heap, int type)
1248
{
1249
    (void)heap;
1250
1251
    if (type == DYNAMIC_TYPE_IN_BUFFER) {
1252
        if (n < sizeof(pool_in))
1253
            return pool_in;
1254
        else
1255
            return NULL;
1256
    }
1257
1258
    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
1259
        if (n < sizeof(pool_out))
1260
            return pool_out;
1261
        else
1262
            return NULL;
1263
    }
1264
1265
    return malloc(n);
1266
}
1267
1268
void* XREALLOC(void *p, size_t n, void* heap, int type)
1269
{
1270
    (void)heap;
1271
1272
    if (type == DYNAMIC_TYPE_IN_BUFFER) {
1273
        if (n < sizeof(pool_in))
1274
            return pool_in;
1275
        else
1276
            return NULL;
1277
    }
1278
1279
    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
1280
        if (n < sizeof(pool_out))
1281
            return pool_out;
1282
        else
1283
            return NULL;
1284
    }
1285
1286
    return realloc(p, n);
1287
}
1288
1289
void XFREE(void *p, void* heap, int type)
1290
{
1291
    (void)heap;
1292
1293
    if (type == DYNAMIC_TYPE_IN_BUFFER)
1294
        return;  /* do nothing, static pool */
1295
1296
    if (type == DYNAMIC_TYPE_OUT_BUFFER)
1297
        return;  /* do nothing, static pool */
1298
1299
    free(p);
1300
}
1301
1302
#endif /* HAVE_IO_POOL */
1303
1304
#ifdef WOLFSSL_MEMORY_LOG
1305
void *xmalloc(size_t n, void* heap, int type, const char* func,
1306
              const char* file, unsigned int line)
1307
{
1308
    void*   p = NULL;
1309
    word32* p32;
1310
1311
#ifdef WOLFSSL_MEM_FAIL_COUNT
1312
    if (!wc_MemFailCount_AllocMem()) {
1313
        WOLFSSL_MSG("MemFailCnt: Fail malloc");
1314
        return NULL;
1315
    }
1316
#endif
1317
1318
    if (malloc_function) {
1319
#ifndef WOLFSSL_STATIC_MEMORY
1320
        p32 = malloc_function(n + sizeof(word32) * 4);
1321
#else
1322
        p32 = malloc_function(n + sizeof(word32) * 4, heap, type);
1323
#endif
1324
    }
1325
    else
1326
        p32 = malloc(n + sizeof(word32) * 4);
1327
1328
    if (p32 != NULL) {
1329
        p32[0] = (word32)n;
1330
        p = (void*)(p32 + 4);
1331
1332
        fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n,
1333
                                                        type, func, file, line);
1334
    }
1335
1336
    (void)heap;
1337
1338
    return p;
1339
}
1340
void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
1341
               const char* file, unsigned int line)
1342
{
1343
    void*   newp = NULL;
1344
    word32* p32;
1345
    word32* oldp32 = NULL;
1346
    word32  oldLen;
1347
1348
#ifdef WOLFSSL_MEM_FAIL_COUNT
1349
    if (!wc_MemFailCount_AllocMem()) {
1350
        WOLFSSL_MSG("MemFailCnt: Fail malloc");
1351
        return NULL;
1352
    }
1353
#endif
1354
1355
    if (p != NULL) {
1356
        oldp32 = (word32*)p;
1357
        oldp32 -= 4;
1358
        oldLen = oldp32[0];
1359
    }
1360
1361
    if (realloc_function) {
1362
#ifndef WOLFSSL_STATIC_MEMORY
1363
        p32 = realloc_function(oldp32, n + sizeof(word32) * 4);
1364
#else
1365
        p32 = realloc_function(oldp32, n + sizeof(word32) * 4, heap, type);
1366
#endif
1367
    }
1368
    else
1369
        p32 = realloc(oldp32, n + sizeof(word32) * 4);
1370
1371
    if (p32 != NULL) {
1372
        p32[0] = (word32)n;
1373
        newp = (void*)(p32 + 4);
1374
1375
        if (p != NULL) {
1376
            fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, oldLen,
1377
                                                        type, func, file, line);
1378
        }
1379
        fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", newp, (word32)n,
1380
                                                        type, func, file, line);
1381
    }
1382
1383
#ifdef WOLFSSL_MEM_FAIL_COUNT
1384
    if (p != NULL) {
1385
        wc_MemFailCount_FreeMem();
1386
    }
1387
#endif
1388
1389
    (void)heap;
1390
1391
    return newp;
1392
}
1393
void xfree(void *p, void* heap, int type, const char* func, const char* file,
1394
           unsigned int line)
1395
{
1396
    word32* p32 = (word32*)p;
1397
1398
    if (p != NULL) {
1399
    #ifdef WOLFSSL_MEM_FAIL_COUNT
1400
        wc_MemFailCount_FreeMem();
1401
    #endif
1402
        p32 -= 4;
1403
1404
        fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type,
1405
                                                              func, file, line);
1406
1407
        if (free_function) {
1408
#ifndef WOLFSSL_STATIC_MEMORY
1409
            free_function(p32);
1410
#else
1411
            free_function(p32, heap, type);
1412
#endif
1413
        }
1414
        else
1415
            free(p32);
1416
    }
1417
1418
    (void)heap;
1419
}
1420
#endif /* WOLFSSL_MEMORY_LOG */
1421
1422
#ifdef WOLFSSL_STACK_LOG
1423
/* Note: this code only works with GCC using -finstrument-functions. */
1424
void __attribute__((no_instrument_function))
1425
     __cyg_profile_func_enter(void *func,  void *caller)
1426
{
1427
    register void* sp asm("sp");
1428
    fprintf(stderr, "ENTER: %016lx %p\n", (unsigned long)(wc_ptr_t)func, sp);
1429
    (void)caller;
1430
}
1431
1432
void __attribute__((no_instrument_function))
1433
     __cyg_profile_func_exit(void *func, void *caller)
1434
{
1435
    register void* sp asm("sp");
1436
    fprintf(stderr, "EXIT: %016lx %p\n", (unsigned long)(wc_ptr_t)func, sp);
1437
    (void)caller;
1438
}
1439
#endif
1440
1441
#ifdef WC_DEBUG_CIPHER_LIFECYCLE
1442
static const byte wc_debug_cipher_lifecycle_tag_value[] =
1443
    { 'W', 'o', 'l', 'f' };
1444
1445
WOLFSSL_LOCAL int wc_debug_CipherLifecycleInit(
1446
    void **CipherLifecycleTag,
1447
    void *heap)
1448
{
1449
    if (CipherLifecycleTag == NULL)
1450
        return BAD_FUNC_ARG;
1451
    *CipherLifecycleTag = (void *)XMALLOC(
1452
        sizeof(wc_debug_cipher_lifecycle_tag_value),
1453
        heap,
1454
        DYNAMIC_TYPE_DEBUG_TAG);
1455
    if (*CipherLifecycleTag == NULL)
1456
        return MEMORY_E;
1457
    XMEMCPY(*CipherLifecycleTag,
1458
            wc_debug_cipher_lifecycle_tag_value,
1459
            sizeof(wc_debug_cipher_lifecycle_tag_value));
1460
    return 0;
1461
}
1462
1463
WOLFSSL_LOCAL int wc_debug_CipherLifecycleCheck(
1464
    void *CipherLifecycleTag,
1465
    int abort_p)
1466
{
1467
    int ret;
1468
    if (CipherLifecycleTag == NULL) {
1469
        ret = BAD_STATE_E;
1470
        goto out;
1471
    }
1472
    if (XMEMCMP(CipherLifecycleTag,
1473
                wc_debug_cipher_lifecycle_tag_value,
1474
                sizeof(wc_debug_cipher_lifecycle_tag_value)) != 0)
1475
    {
1476
        ret = BAD_STATE_E;
1477
        goto out;
1478
    }
1479
    ret = 0;
1480
1481
out:
1482
    if ((ret < 0) && abort_p)
1483
        abort();
1484
1485
    return ret;
1486
}
1487
1488
WOLFSSL_LOCAL int wc_debug_CipherLifecycleFree(
1489
    void **CipherLifecycleTag,
1490
    void *heap,
1491
    int abort_p)
1492
{
1493
    int ret;
1494
    if (CipherLifecycleTag == NULL)
1495
        return BAD_FUNC_ARG;
1496
    ret = wc_debug_CipherLifecycleCheck(*CipherLifecycleTag, abort_p);
1497
    if (ret != 0)
1498
        return ret;
1499
    XFREE(*CipherLifecycleTag, heap, DYNAMIC_TYPE_DEBUG_TAG);
1500
    *CipherLifecycleTag = NULL;
1501
    return 0;
1502
}
1503
#endif /* WC_DEBUG_CIPHER_LIFECYCLE */
1504
1505
#ifdef DEBUG_VECTOR_REGISTER_ACCESS
1506
THREAD_LS_T int wc_svr_count = 0;
1507
THREAD_LS_T const char *wc_svr_last_file = NULL;
1508
THREAD_LS_T int wc_svr_last_line = -1;
1509
THREAD_LS_T int wc_debug_vector_registers_retval =
1510
    WC_DEBUG_VECTOR_REGISTERS_RETVAL_INITVAL;
1511
1512
#ifdef DEBUG_VECTOR_REGISTER_ACCESS_FUZZING
1513
1514
WOLFSSL_LOCAL int SAVE_VECTOR_REGISTERS2_fuzzer(void) {
1515
    static THREAD_LS_T struct drand48_data wc_svr_fuzzing_state;
1516
    static THREAD_LS_T int wc_svr_fuzzing_seeded = 0;
1517
    long result;
1518
1519
    if (wc_debug_vector_registers_retval)
1520
        return wc_debug_vector_registers_retval;
1521
1522
    if (wc_svr_fuzzing_seeded == 0) {
1523
        long seed = WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED;
1524
        char *seed_envstr = getenv("WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED");
1525
        if (seed_envstr)
1526
            seed = strtol(seed_envstr, NULL, 0);
1527
        (void)srand48_r(seed, &wc_svr_fuzzing_state);
1528
        wc_svr_fuzzing_seeded = 1;
1529
    }
1530
    (void)lrand48_r(&wc_svr_fuzzing_state, &result);
1531
    if (result & 1)
1532
        return IO_FAILED_E;
1533
    else
1534
        return 0;
1535
}
1536
1537
#endif
1538
1539
#endif
1540
1541
#ifdef WOLFSSL_LINUXKM
1542
    #include "../../linuxkm/linuxkm_memory.c"
1543
#endif