source: azure_iot_hub/trunk/wolfssl-3.15.7/wolfcrypt/src/memory.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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