source: azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/wolfcrypt/src/memory.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 31.9 KB
Line 
1/* memory.c
2 *
3 * Copyright (C) 2006-2020 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#include <wolfssl/wolfcrypt/settings.h>
28
29/* check old macros @wc_fips */
30#if defined(USE_CYASSL_MEMORY) && !defined(USE_WOLFSSL_MEMORY)
31 #define USE_WOLFSSL_MEMORY
32#endif
33#if defined(CYASSL_MALLOC_CHECK) && !defined(WOLFSSL_MALLOC_CHECK)
34 #define WOLFSSL_MALLOC_CHECK
35#endif
36
37
38/*
39Possible memory options:
40 * NO_WOLFSSL_MEMORY: Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY.
41 * WOLFSSL_STATIC_MEMORY: Turns on the use of static memory buffers and functions.
42 This allows for using static memory instead of dynamic.
43 * WOLFSSL_STATIC_ALIGN: Define defaults to 16 to indicate static memory alignment.
44 * HAVE_IO_POOL: Enables use of static thread safe memory pool for input/output buffers.
45 * XMALLOC_OVERRIDE: Allows override of the XMALLOC, XFREE and XREALLOC macros.
46 * XMALLOC_USER: Allows custom XMALLOC, XFREE and XREALLOC functions to be defined.
47 * WOLFSSL_NO_MALLOC: Disables the fall-back case to use STDIO malloc/free when no callbacks are set.
48 * WOLFSSL_TRACK_MEMORY: Enables memory tracking for total stats and list of allocated memory.
49 * WOLFSSL_DEBUG_MEMORY: Enables extra function and line number args for memory callbacks.
50 * WOLFSSL_DEBUG_MEMORY_PRINT: Enables printing of each malloc/free.
51 * WOLFSSL_MALLOC_CHECK: Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN
52 * WOLFSSL_FORCE_MALLOC_FAIL_TEST: Used for internal testing to induce random malloc failures.
53 * WOLFSSL_HEAP_TEST: Used for internal testing of heap hint
54 */
55
56#ifdef WOLFSSL_ZEPHYR
57#undef realloc
58void *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. */
98static wolfSSL_Malloc_cb malloc_function = NULL;
99static wolfSSL_Free_cb free_function = NULL;
100static wolfSSL_Realloc_cb realloc_function = NULL;
101
102int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf,
103 wolfSSL_Free_cb ff,
104 wolfSSL_Realloc_cb rf)
105{
106 malloc_function = mf;
107 free_function = ff;
108 realloc_function = rf;
109 return 0;
110}
111
112int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf,
113 wolfSSL_Free_cb* ff,
114 wolfSSL_Realloc_cb* rf)
115{
116 if (mf) *mf = malloc_function;
117 if (ff) *ff = free_function;
118 if (rf) *rf = realloc_function;
119 return 0;
120}
121
122#ifndef WOLFSSL_STATIC_MEMORY
123#ifdef WOLFSSL_DEBUG_MEMORY
124void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
125#else
126void* wolfSSL_Malloc(size_t size)
127#endif
128{
129 void* res = 0;
130
131 if (malloc_function) {
132 #ifdef WOLFSSL_DEBUG_MEMORY
133 res = malloc_function(size, func, line);
134 #else
135 res = malloc_function(size);
136 #endif
137 }
138 else {
139 #ifndef WOLFSSL_NO_MALLOC
140 res = malloc(size);
141 #else
142 WOLFSSL_MSG("No malloc available");
143 #endif
144 }
145
146#ifdef WOLFSSL_DEBUG_MEMORY
147#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
148 printf("Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line);
149#else
150 (void)func;
151 (void)line;
152#endif
153#endif
154
155#ifdef WOLFSSL_MALLOC_CHECK
156 if (res == NULL)
157 WOLFSSL_MSG("wolfSSL_malloc failed");
158#endif
159
160#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
161 if (res && --gMemFailCount == 0) {
162 printf("\n---FORCED MEM FAIL TEST---\n");
163 if (free_function) {
164 #ifdef WOLFSSL_DEBUG_MEMORY
165 free_function(res, func, line);
166 #else
167 free_function(res);
168 #endif
169 }
170 else {
171 free(res); /* clear */
172 }
173 gMemFailCount = gMemFailCountSeed; /* reset */
174 return NULL;
175 }
176#endif
177
178 return res;
179}
180
181#ifdef WOLFSSL_DEBUG_MEMORY
182void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
183#else
184void wolfSSL_Free(void *ptr)
185#endif
186{
187#ifdef WOLFSSL_DEBUG_MEMORY
188#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
189 printf("Free: %p at %s:%d\n", ptr, func, line);
190#else
191 (void)func;
192 (void)line;
193#endif
194#endif
195
196 if (free_function) {
197 #ifdef WOLFSSL_DEBUG_MEMORY
198 free_function(ptr, func, line);
199 #else
200 free_function(ptr);
201 #endif
202 }
203 else {
204 #ifndef WOLFSSL_NO_MALLOC
205 free(ptr);
206 #else
207 WOLFSSL_MSG("No free available");
208 #endif
209 }
210}
211
212#ifdef WOLFSSL_DEBUG_MEMORY
213void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
214#else
215void* wolfSSL_Realloc(void *ptr, size_t size)
216#endif
217{
218 void* res = 0;
219
220 if (realloc_function) {
221 #ifdef WOLFSSL_DEBUG_MEMORY
222 res = realloc_function(ptr, size, func, line);
223 #else
224 res = realloc_function(ptr, size);
225 #endif
226 }
227 else {
228 #ifndef WOLFSSL_NO_MALLOC
229 res = realloc(ptr, size);
230 #else
231 WOLFSSL_MSG("No realloc available");
232 #endif
233 }
234
235 return res;
236}
237#endif /* WOLFSSL_STATIC_MEMORY */
238
239#ifdef WOLFSSL_STATIC_MEMORY
240
241struct wc_Memory {
242 byte* buffer;
243 struct wc_Memory* next;
244 word32 sz;
245};
246
247
248/* returns amount of memory used on success. On error returns negative value
249 wc_Memory** list is the list that new buckets are prepended to
250 */
251static int create_memory_buckets(byte* buffer, word32 bufSz,
252 word32 buckSz, word32 buckNum, wc_Memory** list) {
253 word32 i;
254 byte* pt = buffer;
255 int ret = 0;
256 word32 memSz = (word32)sizeof(wc_Memory);
257 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
258
259 /* if not enough space available for bucket size then do not try */
260 if (buckSz + memSz + padSz > bufSz) {
261 return ret;
262 }
263
264 for (i = 0; i < buckNum; i++) {
265 if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
266 /* create a new struct and set its values */
267 wc_Memory* mem = (struct wc_Memory*)(pt);
268 mem->sz = buckSz;
269 mem->buffer = (byte*)pt + padSz + memSz;
270 mem->next = NULL;
271
272 /* add the newly created struct to front of list */
273 if (*list == NULL) {
274 *list = mem;
275 } else {
276 mem->next = *list;
277 *list = mem;
278 }
279
280 /* advance pointer and keep track of memory used */
281 ret += buckSz + padSz + memSz;
282 pt += buckSz + padSz + memSz;
283 }
284 else {
285 break; /* not enough space left for more buckets of this size */
286 }
287 }
288
289 return ret;
290}
291
292int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap)
293{
294 word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
295 word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST };
296
297 if (heap == NULL) {
298 return BAD_FUNC_ARG;
299 }
300
301 XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
302
303 XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz));
304 XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist));
305
306 if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
307 WOLFSSL_MSG("Error creating heap memory mutex");
308 return BAD_MUTEX_E;
309 }
310
311 return 0;
312}
313
314int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
315 unsigned char* buf, unsigned int sz, int flag, int max)
316{
317 int ret;
318 WOLFSSL_HEAP* heap;
319 WOLFSSL_HEAP_HINT* hint;
320 word32 idx = 0;
321
322 if (pHint == NULL || buf == NULL) {
323 return BAD_FUNC_ARG;
324 }
325
326 if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
327 return BUFFER_E; /* not enough memory for structures */
328 }
329
330 /* check if hint has already been assigned */
331 if (*pHint == NULL) {
332 heap = (WOLFSSL_HEAP*)buf;
333 idx += sizeof(WOLFSSL_HEAP);
334 hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
335 idx += sizeof(WOLFSSL_HEAP_HINT);
336
337 ret = wolfSSL_init_memory_heap(heap);
338 if (ret != 0) {
339 return ret;
340 }
341
342 XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
343 hint->memory = heap;
344 }
345 else {
346 #ifdef WOLFSSL_HEAP_TEST
347 /* do not load in memory if test has been set */
348 if (heap == (void*)WOLFSSL_HEAP_TEST) {
349 return 0;
350 }
351 #endif
352
353 hint = (WOLFSSL_HEAP_HINT*)(*pHint);
354 heap = hint->memory;
355 }
356
357 ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap);
358 if (ret != 1) {
359 WOLFSSL_MSG("Error partitioning memory");
360 return -1;
361 }
362
363 /* determine what max applies too */
364 if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
365 heap->maxIO = max;
366 }
367 else { /* general memory used in handshakes */
368 heap->maxHa = max;
369 }
370
371 heap->flag |= flag;
372 *pHint = hint;
373
374 (void)max;
375
376 return 0;
377}
378
379int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
380 WOLFSSL_HEAP* heap)
381{
382 word32 ava = sz;
383 byte* pt = buffer;
384 int ret = 0;
385 word32 memSz = (word32)sizeof(wc_Memory);
386 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
387
388 WOLFSSL_ENTER("wolfSSL_load_static_memory");
389
390 if (buffer == NULL) {
391 return BAD_FUNC_ARG;
392 }
393
394 /* align pt */
395 while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
396 *pt = 0x00;
397 pt++;
398 ava--;
399 }
400
401#ifdef WOLFSSL_DEBUG_MEMORY
402 printf("Allocated %d bytes for static memory @ %p\n", ava, pt);
403#endif
404
405 /* divide into chunks of memory and add them to available list */
406 while (ava >= (heap->sizeList[0] + padSz + memSz)) {
407 int i;
408 /* creating only IO buffers from memory passed in, max TLS is 16k */
409 if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
410 if ((ret = create_memory_buckets(pt, ava,
411 WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
412 WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
413 return ret;
414 }
415
416 /* check if no more room left for creating IO buffers */
417 if (ret == 0) {
418 break;
419 }
420
421 /* advance pointer in buffer for next buckets and keep track
422 of how much memory is left available */
423 pt += ret;
424 ava -= ret;
425 }
426 else {
427 /* start at largest and move to smaller buckets */
428 for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
429 if ((heap->sizeList[i] + padSz + memSz) <= ava) {
430 if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
431 heap->distList[i], &(heap->ava[i]))) < 0) {
432 WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
433 return ret;
434 }
435
436 /* advance pointer in buffer for next buckets and keep track
437 of how much memory is left available */
438 pt += ret;
439 ava -= ret;
440 }
441 }
442 }
443 }
444
445 return 1;
446}
447
448
449/* returns the size of management memory needed for each bucket.
450 * This is memory that is used to keep track of and align memory buckets. */
451int wolfSSL_MemoryPaddingSz(void)
452{
453 word32 memSz = (word32)sizeof(wc_Memory);
454 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
455 return memSz + padSz;
456}
457
458
459/* Used to calculate memory size for optimum use with buckets.
460 returns the suggested size rounded down to the nearest bucket. */
461int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
462{
463 word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS};
464 word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST};
465
466 word32 ava = sz;
467 byte* pt = buffer;
468 word32 memSz = (word32)sizeof(wc_Memory);
469 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
470
471 WOLFSSL_ENTER("wolfSSL_static_size");
472
473 if (buffer == NULL) {
474 return BAD_FUNC_ARG;
475 }
476
477 /* align pt */
478 while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
479 pt++;
480 ava--;
481 }
482
483 /* creating only IO buffers from memory passed in, max TLS is 16k */
484 if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
485 if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
486 return 0; /* not enough room for even one bucket */
487 }
488
489 ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
490 }
491 else {
492 int i, k;
493
494 if (ava < (bucketSz[0] + padSz + memSz)) {
495 return 0; /* not enough room for even one bucket */
496 }
497
498 while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) {
499 /* start at largest and move to smaller buckets */
500 for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
501 for (k = distList[i]; k > 0; k--) {
502 if ((bucketSz[i] + padSz + memSz) <= ava) {
503 ava -= bucketSz[i] + padSz + memSz;
504 }
505 }
506 }
507 }
508 }
509
510 return sz - ava; /* round down */
511}
512
513
514int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
515{
516 WOLFSSL_MSG("Freeing fixed IO buffer");
517
518 /* check if fixed buffer was set */
519 if (*io == NULL) {
520 return 1;
521 }
522
523 if (heap == NULL) {
524 WOLFSSL_MSG("No heap to return fixed IO too");
525 }
526 else {
527 /* put IO buffer back into IO pool */
528 (*io)->next = heap->io;
529 heap->io = *io;
530 *io = NULL;
531 }
532
533 return 1;
534}
535
536
537int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
538{
539 WOLFSSL_MSG("Setting fixed IO for SSL");
540 if (heap == NULL) {
541 return MEMORY_E;
542 }
543
544 *io = heap->io;
545
546 if (*io != NULL) {
547 heap->io = (*io)->next;
548 (*io)->next = NULL;
549 }
550 else { /* failed to grab an IO buffer */
551 return 0;
552 }
553
554 return 1;
555}
556
557
558int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
559{
560 word32 i;
561 wc_Memory* pt;
562
563 XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
564
565 stats->totalAlloc = heap->alloc;
566 stats->totalFr = heap->frAlc;
567 stats->curAlloc = stats->totalAlloc - stats->totalFr;
568 stats->maxHa = heap->maxHa;
569 stats->maxIO = heap->maxIO;
570 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
571 stats->blockSz[i] = heap->sizeList[i];
572 for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
573 stats->avaBlock[i] += 1;
574 }
575 }
576
577 for (pt = heap->io; pt != NULL; pt = pt->next) {
578 stats->avaIO++;
579 }
580
581 stats->flag = heap->flag; /* flag used */
582
583 return 1;
584}
585
586
587#ifdef WOLFSSL_DEBUG_MEMORY
588void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
589#else
590void* wolfSSL_Malloc(size_t size, void* heap, int type)
591#endif
592{
593 void* res = 0;
594 wc_Memory* pt = NULL;
595 int i;
596
597 /* check for testing heap hint was set */
598#ifdef WOLFSSL_HEAP_TEST
599 if (heap == (void*)WOLFSSL_HEAP_TEST) {
600 return malloc(size);
601 }
602#endif
603
604 /* if no heap hint then use dynamic memory*/
605 if (heap == NULL) {
606 #ifdef WOLFSSL_HEAP_TEST
607 /* allow using malloc for creating ctx and method */
608 if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
609 type == DYNAMIC_TYPE_CERT_MANAGER) {
610 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
611 res = malloc(size);
612 }
613 else {
614 WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n");
615 res = NULL;
616 }
617 #else
618 #ifndef WOLFSSL_NO_MALLOC
619 #ifdef FREERTOS
620 res = pvPortMalloc(size);
621 #else
622 res = malloc(size);
623 #endif
624 #else
625 WOLFSSL_MSG("No heap hint found to use and no malloc");
626 #ifdef WOLFSSL_DEBUG_MEMORY
627 printf("ERROR: at %s:%d\n", func, line);
628 #endif
629 #endif /* WOLFSSL_NO_MALLOC */
630 #endif /* WOLFSSL_HEAP_TEST */
631 }
632 else {
633 WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
634 WOLFSSL_HEAP* mem = hint->memory;
635
636 if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
637 WOLFSSL_MSG("Bad memory_mutex lock");
638 return NULL;
639 }
640
641 /* case of using fixed IO buffers */
642 if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
643 (type == DYNAMIC_TYPE_OUT_BUFFER ||
644 type == DYNAMIC_TYPE_IN_BUFFER)) {
645 if (type == DYNAMIC_TYPE_OUT_BUFFER) {
646 pt = hint->outBuf;
647 }
648 if (type == DYNAMIC_TYPE_IN_BUFFER) {
649 pt = hint->inBuf;
650 }
651 }
652 else {
653 /* check if using IO pool flag */
654 if (mem->flag & WOLFMEM_IO_POOL &&
655 (type == DYNAMIC_TYPE_OUT_BUFFER ||
656 type == DYNAMIC_TYPE_IN_BUFFER)) {
657 if (mem->io != NULL) {
658 pt = mem->io;
659 mem->io = pt->next;
660 }
661 }
662
663 /* general static memory */
664 if (pt == NULL) {
665 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
666 if ((word32)size < mem->sizeList[i]) {
667 if (mem->ava[i] != NULL) {
668 pt = mem->ava[i];
669 mem->ava[i] = pt->next;
670 break;
671 }
672 #ifdef WOLFSSL_DEBUG_STATIC_MEMORY
673 else {
674 printf("Size: %ld, Empty: %d\n", size,
675 mem->sizeList[i]);
676 }
677 #endif
678 }
679 }
680 }
681 }
682
683 if (pt != NULL) {
684 mem->inUse += pt->sz;
685 mem->alloc += 1;
686 res = pt->buffer;
687
688 #ifdef WOLFSSL_DEBUG_MEMORY
689 printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
690 #endif
691
692 /* keep track of connection statistics if flag is set */
693 if (mem->flag & WOLFMEM_TRACK_STATS) {
694 WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
695 if (stats != NULL) {
696 stats->curMem += pt->sz;
697 if (stats->peakMem < stats->curMem) {
698 stats->peakMem = stats->curMem;
699 }
700 stats->curAlloc++;
701 if (stats->peakAlloc < stats->curAlloc) {
702 stats->peakAlloc = stats->curAlloc;
703 }
704 stats->totalAlloc++;
705 }
706 }
707 }
708 else {
709 WOLFSSL_MSG("ERROR ran out of static memory");
710 #ifdef WOLFSSL_DEBUG_MEMORY
711 printf("Looking for %lu bytes at %s:%d\n", size, func, line);
712 #endif
713 }
714
715 wc_UnLockMutex(&(mem->memory_mutex));
716 }
717
718 #ifdef WOLFSSL_MALLOC_CHECK
719 if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
720 WOLFSSL_MSG("ERROR memory is not aligned");
721 res = NULL;
722 }
723 #endif
724
725
726 (void)i;
727 (void)pt;
728 (void)type;
729
730 return res;
731}
732
733
734#ifdef WOLFSSL_DEBUG_MEMORY
735void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
736#else
737void wolfSSL_Free(void *ptr, void* heap, int type)
738#endif
739{
740 int i;
741 wc_Memory* pt;
742
743 if (ptr) {
744 /* check for testing heap hint was set */
745 #ifdef WOLFSSL_HEAP_TEST
746 if (heap == (void*)WOLFSSL_HEAP_TEST) {
747 return free(ptr);
748 }
749 #endif
750
751 if (heap == NULL) {
752 #ifdef WOLFSSL_HEAP_TEST
753 /* allow using malloc for creating ctx and method */
754 if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
755 type == DYNAMIC_TYPE_CERT_MANAGER) {
756 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
757 }
758 else {
759 WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n");
760 }
761 #endif
762 #ifndef WOLFSSL_NO_MALLOC
763 #ifdef FREERTOS
764 vPortFree(ptr);
765 #else
766 free(ptr);
767 #endif
768 #else
769 WOLFSSL_MSG("Error trying to call free when turned off");
770 #endif /* WOLFSSL_NO_MALLOC */
771 }
772 else {
773 WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
774 WOLFSSL_HEAP* mem = hint->memory;
775 word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
776
777 /* get memory struct and add it to available list */
778 pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
779 if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
780 WOLFSSL_MSG("Bad memory_mutex lock");
781 return;
782 }
783
784 /* case of using fixed IO buffers */
785 if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
786 (type == DYNAMIC_TYPE_OUT_BUFFER ||
787 type == DYNAMIC_TYPE_IN_BUFFER)) {
788 /* fixed IO pools are free'd at the end of SSL lifetime
789 using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
790 }
791 else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
792 (type == DYNAMIC_TYPE_OUT_BUFFER ||
793 type == DYNAMIC_TYPE_IN_BUFFER)) {
794 pt->next = mem->io;
795 mem->io = pt;
796 }
797 else { /* general memory free */
798 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
799 if (pt->sz == mem->sizeList[i]) {
800 pt->next = mem->ava[i];
801 mem->ava[i] = pt;
802 break;
803 }
804 }
805 }
806 mem->inUse -= pt->sz;
807 mem->frAlc += 1;
808
809 #ifdef WOLFSSL_DEBUG_MEMORY
810 printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
811 #endif
812
813 /* keep track of connection statistics if flag is set */
814 if (mem->flag & WOLFMEM_TRACK_STATS) {
815 WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
816 if (stats != NULL) {
817 /* avoid under flow */
818 if (stats->curMem > pt->sz) {
819 stats->curMem -= pt->sz;
820 }
821 else {
822 stats->curMem = 0;
823 }
824
825 if (stats->curAlloc > 0) {
826 stats->curAlloc--;
827 }
828 stats->totalFr++;
829 }
830 }
831 wc_UnLockMutex(&(mem->memory_mutex));
832 }
833 }
834
835 (void)i;
836 (void)pt;
837 (void)type;
838}
839
840#ifdef WOLFSSL_DEBUG_MEMORY
841void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
842#else
843void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
844#endif
845{
846 void* res = 0;
847 wc_Memory* pt = NULL;
848 word32 prvSz;
849 int i;
850
851 /* check for testing heap hint was set */
852#ifdef WOLFSSL_HEAP_TEST
853 if (heap == (void*)WOLFSSL_HEAP_TEST) {
854 return realloc(ptr, size);
855 }
856#endif
857
858 if (heap == NULL) {
859 #ifdef WOLFSSL_HEAP_TEST
860 WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n");
861 #endif
862 #ifndef WOLFSSL_NO_MALLOC
863 res = realloc(ptr, size);
864 #else
865 WOLFSSL_MSG("NO heap found to use for realloc");
866 #endif /* WOLFSSL_NO_MALLOC */
867 }
868 else {
869 WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
870 WOLFSSL_HEAP* mem = hint->memory;
871 word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
872
873 if (ptr == NULL) {
874 #ifdef WOLFSSL_DEBUG_MEMORY
875 return wolfSSL_Malloc(size, heap, type, func, line);
876 #else
877 return wolfSSL_Malloc(size, heap, type);
878 #endif
879 }
880
881 if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
882 WOLFSSL_MSG("Bad memory_mutex lock");
883 return NULL;
884 }
885
886 /* case of using fixed IO buffers or IO pool */
887 if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
888 && (type == DYNAMIC_TYPE_OUT_BUFFER ||
889 type == DYNAMIC_TYPE_IN_BUFFER)) {
890 /* no realloc, is fixed size */
891 pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
892 if (pt->sz < size) {
893 WOLFSSL_MSG("Error IO memory was not large enough");
894 res = NULL; /* return NULL in error case */
895 }
896 res = pt->buffer;
897 }
898 else {
899 /* general memory */
900 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
901 if ((word32)size < mem->sizeList[i]) {
902 if (mem->ava[i] != NULL) {
903 pt = mem->ava[i];
904 mem->ava[i] = pt->next;
905 break;
906 }
907 }
908 }
909
910 if (pt != NULL && res == NULL) {
911 res = pt->buffer;
912
913 /* copy over original information and free ptr */
914 prvSz = ((wc_Memory*)((byte*)ptr - padSz -
915 sizeof(wc_Memory)))->sz;
916 prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
917 XMEMCPY(pt->buffer, ptr, prvSz);
918 mem->inUse += pt->sz;
919 mem->alloc += 1;
920
921 /* free memory that was previously being used */
922 wc_UnLockMutex(&(mem->memory_mutex));
923 wolfSSL_Free(ptr, heap, type
924 #ifdef WOLFSSL_DEBUG_MEMORY
925 , func, line
926 #endif
927 );
928 if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
929 WOLFSSL_MSG("Bad memory_mutex lock");
930 return NULL;
931 }
932 }
933 }
934 wc_UnLockMutex(&(mem->memory_mutex));
935 }
936
937 #ifdef WOLFSSL_MALLOC_CHECK
938 if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
939 WOLFSSL_MSG("ERROR memory is not aligned");
940 res = NULL;
941 }
942 #endif
943
944 (void)i;
945 (void)pt;
946 (void)type;
947
948 return res;
949}
950#endif /* WOLFSSL_STATIC_MEMORY */
951
952#endif /* USE_WOLFSSL_MEMORY */
953
954
955#ifdef HAVE_IO_POOL
956
957/* Example for user io pool, shared build may need definitions in lib proper */
958
959#include <wolfssl/wolfcrypt/types.h>
960#include <stdlib.h>
961
962#ifndef HAVE_THREAD_LS
963 #error "Oops, simple I/O pool example needs thread local storage"
964#endif
965
966
967/* allow simple per thread in and out pools */
968/* use 17k size since max record size is 16k plus overhead */
969static THREAD_LS_T byte pool_in[17*1024];
970static THREAD_LS_T byte pool_out[17*1024];
971
972
973void* XMALLOC(size_t n, void* heap, int type)
974{
975 (void)heap;
976
977 if (type == DYNAMIC_TYPE_IN_BUFFER) {
978 if (n < sizeof(pool_in))
979 return pool_in;
980 else
981 return NULL;
982 }
983
984 if (type == DYNAMIC_TYPE_OUT_BUFFER) {
985 if (n < sizeof(pool_out))
986 return pool_out;
987 else
988 return NULL;
989 }
990
991 return malloc(n);
992}
993
994void* XREALLOC(void *p, size_t n, void* heap, int type)
995{
996 (void)heap;
997
998 if (type == DYNAMIC_TYPE_IN_BUFFER) {
999 if (n < sizeof(pool_in))
1000 return pool_in;
1001 else
1002 return NULL;
1003 }
1004
1005 if (type == DYNAMIC_TYPE_OUT_BUFFER) {
1006 if (n < sizeof(pool_out))
1007 return pool_out;
1008 else
1009 return NULL;
1010 }
1011
1012 return realloc(p, n);
1013}
1014
1015void XFREE(void *p, void* heap, int type)
1016{
1017 (void)heap;
1018
1019 if (type == DYNAMIC_TYPE_IN_BUFFER)
1020 return; /* do nothing, static pool */
1021
1022 if (type == DYNAMIC_TYPE_OUT_BUFFER)
1023 return; /* do nothing, static pool */
1024
1025 free(p);
1026}
1027
1028#endif /* HAVE_IO_POOL */
1029
1030#ifdef WOLFSSL_MEMORY_LOG
1031void *xmalloc(size_t n, void* heap, int type, const char* func,
1032 const char* file, unsigned int line)
1033{
1034 void* p;
1035 word32* p32;
1036
1037 if (malloc_function)
1038 p32 = malloc_function(n + sizeof(word32) * 4);
1039 else
1040 p32 = malloc(n + sizeof(word32) * 4);
1041
1042 p32[0] = (word32)n;
1043 p = (void*)(p32 + 4);
1044
1045 fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n, type,
1046 func, file, line);
1047
1048 (void)heap;
1049
1050 return p;
1051}
1052void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
1053 const char* file, unsigned int line)
1054{
1055 void* newp = NULL;
1056 word32* p32;
1057 word32* oldp32 = NULL;
1058 word32 oldLen;
1059
1060 if (p != NULL) {
1061 oldp32 = (word32*)p;
1062 oldp32 -= 4;
1063 oldLen = oldp32[0];
1064 }
1065
1066 if (realloc_function)
1067 p32 = realloc_function(oldp32, n + sizeof(word32) * 4);
1068 else
1069 p32 = realloc(oldp32, n + sizeof(word32) * 4);
1070
1071 if (p32 != NULL) {
1072 p32[0] = (word32)n;
1073 newp = (void*)(p32 + 4);
1074
1075 fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", newp, (word32)n,
1076 type, func, file, line);
1077 if (p != NULL) {
1078 fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, oldLen,
1079 type, func, file, line);
1080 }
1081 }
1082
1083 (void)heap;
1084
1085 return newp;
1086}
1087void xfree(void *p, void* heap, int type, const char* func, const char* file,
1088 unsigned int line)
1089{
1090 word32* p32 = (word32*)p;
1091
1092 if (p != NULL) {
1093 p32 -= 4;
1094
1095 fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type,
1096 func, file, line);
1097
1098 if (free_function)
1099 free_function(p32);
1100 else
1101 free(p32);
1102 }
1103
1104 (void)heap;
1105}
1106#endif /* WOLFSSL_MEMORY_LOG */
1107
1108#ifdef WOLFSSL_STACK_LOG
1109/* Note: this code only works with GCC using -finstrument-functions. */
1110void __attribute__((no_instrument_function))
1111 __cyg_profile_func_enter(void *func, void *caller)
1112{
1113 register void* sp asm("sp");
1114 fprintf(stderr, "ENTER: %016lx %p\n", (unsigned long)(size_t)func, sp);
1115 (void)caller;
1116}
1117
1118void __attribute__((no_instrument_function))
1119 __cyg_profile_func_exit(void *func, void *caller)
1120{
1121 register void* sp asm("sp");
1122 fprintf(stderr, "EXIT: %016lx %p\n", (unsigned long)(size_t)func, sp);
1123 (void)caller;
1124}
1125#endif
1126
Note: See TracBrowser for help on using the repository browser.