Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
memory.c
00001 /* memory.c 00002 * 00003 * Copyright (C) 2006-2017 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfcrypt/settings.h> 00028 00029 /* check old macros @wc_fips */ 00030 #if defined(USE_CYASSL_MEMORY) && !defined(USE_WOLFSSL_MEMORY) 00031 #define USE_WOLFSSL_MEMORY 00032 #endif 00033 #if defined(CYASSL_MALLOC_CHECK) && !defined(WOLFSSL_MALLOC_CHECK) 00034 #define WOLFSSL_MALLOC_CHECK 00035 #endif 00036 00037 #ifdef USE_WOLFSSL_MEMORY 00038 00039 #include <wolfcrypt/memory.h> 00040 #include <wolfcrypt/error-crypt.h> 00041 #include <wolfcrypt/logging.h> 00042 00043 #if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) 00044 #include <stdio.h> 00045 #endif 00046 00047 00048 /* Set these to default values initially. */ 00049 static wolfSSL_Malloc_cb malloc_function = NULL; 00050 static wolfSSL_Free_cb free_function = NULL; 00051 static wolfSSL_Realloc_cb realloc_function = NULL; 00052 00053 int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf, 00054 wolfSSL_Free_cb ff, 00055 wolfSSL_Realloc_cb rf) 00056 { 00057 int res = 0; 00058 00059 if (mf) 00060 malloc_function = mf; 00061 else 00062 res = BAD_FUNC_ARG; 00063 00064 if (ff) 00065 free_function = ff; 00066 else 00067 res = BAD_FUNC_ARG; 00068 00069 if (rf) 00070 realloc_function = rf; 00071 else 00072 res = BAD_FUNC_ARG; 00073 00074 return res; 00075 } 00076 00077 int wolfSSL_ResetAllocators(void) 00078 { 00079 /* allow nulls to be set for callbacks to restore defaults */ 00080 malloc_function = NULL; 00081 free_function = NULL; 00082 realloc_function = NULL; 00083 00084 return 0; 00085 } 00086 00087 int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, 00088 wolfSSL_Free_cb* ff, 00089 wolfSSL_Realloc_cb* rf) 00090 { 00091 if (mf) *mf = malloc_function; 00092 if (ff) *ff = free_function; 00093 if (rf) *rf = realloc_function; 00094 return 0; 00095 } 00096 00097 #ifndef WOLFSSL_STATIC_MEMORY 00098 #ifdef WOLFSSL_DEBUG_MEMORY 00099 void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line) 00100 #else 00101 void* wolfSSL_Malloc(size_t size) 00102 #endif 00103 { 00104 void* res = 0; 00105 00106 if (malloc_function) { 00107 #ifdef WOLFSSL_DEBUG_MEMORY 00108 res = malloc_function(size, func, line); 00109 #else 00110 res = malloc_function(size); 00111 #endif 00112 } 00113 else { 00114 #ifndef WOLFSSL_NO_MALLOC 00115 res = malloc(size); 00116 #else 00117 WOLFSSL_MSG("No malloc available"); 00118 #endif 00119 } 00120 00121 #ifdef WOLFSSL_MALLOC_CHECK 00122 if (res == NULL) 00123 puts("wolfSSL_malloc failed"); 00124 #endif 00125 00126 return res; 00127 } 00128 00129 #ifdef WOLFSSL_DEBUG_MEMORY 00130 void wolfSSL_Free(void *ptr, const char* func, unsigned int line) 00131 #else 00132 void wolfSSL_Free(void *ptr) 00133 #endif 00134 { 00135 if (free_function) { 00136 #ifdef WOLFSSL_DEBUG_MEMORY 00137 free_function(ptr, func, line); 00138 #else 00139 free_function(ptr); 00140 #endif 00141 } 00142 else { 00143 #ifndef WOLFSSL_NO_MALLOC 00144 free(ptr); 00145 #else 00146 WOLFSSL_MSG("No free available"); 00147 #endif 00148 } 00149 } 00150 00151 #ifdef WOLFSSL_DEBUG_MEMORY 00152 void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line) 00153 #else 00154 void* wolfSSL_Realloc(void *ptr, size_t size) 00155 #endif 00156 { 00157 void* res = 0; 00158 00159 if (realloc_function) { 00160 #ifdef WOLFSSL_DEBUG_MEMORY 00161 res = realloc_function(ptr, size, func, line); 00162 #else 00163 res = realloc_function(ptr, size); 00164 #endif 00165 } 00166 else { 00167 #ifndef WOLFSSL_NO_MALLOC 00168 res = realloc(ptr, size); 00169 #else 00170 WOLFSSL_MSG("No realloc available"); 00171 #endif 00172 } 00173 00174 return res; 00175 } 00176 #endif /* WOLFSSL_STATIC_MEMORY */ 00177 00178 #ifdef WOLFSSL_STATIC_MEMORY 00179 00180 struct wc_Memory { 00181 byte* buffer; 00182 struct wc_Memory* next; 00183 word32 sz; 00184 }; 00185 00186 00187 /* returns amount of memory used on success. On error returns negative value 00188 wc_Memory** list is the list that new buckets are prepended to 00189 */ 00190 static int create_memory_buckets(byte* buffer, word32 bufSz, 00191 word32 buckSz, word32 buckNum, wc_Memory** list) { 00192 word32 i; 00193 byte* pt = buffer; 00194 int ret = 0; 00195 word32 memSz = (word32)sizeof(wc_Memory); 00196 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); 00197 00198 /* if not enough space available for bucket size then do not try */ 00199 if (buckSz + memSz + padSz > bufSz) { 00200 return ret; 00201 } 00202 00203 for (i = 0; i < buckNum; i++) { 00204 if ((buckSz + memSz + padSz) <= (bufSz - ret)) { 00205 /* create a new struct and set its values */ 00206 wc_Memory* mem = (struct wc_Memory*)(pt); 00207 mem->sz = buckSz; 00208 mem->buffer = (byte*)pt + padSz + memSz; 00209 mem->next = NULL; 00210 00211 /* add the newly created struct to front of list */ 00212 if (*list == NULL) { 00213 *list = mem; 00214 } else { 00215 mem->next = *list; 00216 *list = mem; 00217 } 00218 00219 /* advance pointer and keep track of memory used */ 00220 ret += buckSz + padSz + memSz; 00221 pt += buckSz + padSz + memSz; 00222 } 00223 else { 00224 break; /* not enough space left for more buckets of this size */ 00225 } 00226 } 00227 00228 return ret; 00229 } 00230 00231 int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) 00232 { 00233 word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; 00234 word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; 00235 00236 if (heap == NULL) { 00237 return BAD_FUNC_ARG; 00238 } 00239 00240 XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); 00241 00242 XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); 00243 XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); 00244 00245 if (wc_InitMutex(&(heap->memory_mutex)) != 0) { 00246 WOLFSSL_MSG("Error creating heap memory mutex"); 00247 return BAD_MUTEX_E; 00248 } 00249 00250 return 0; 00251 } 00252 00253 int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, 00254 unsigned char* buf, unsigned int sz, int flag, int max) 00255 { 00256 int ret; 00257 WOLFSSL_HEAP* heap; 00258 WOLFSSL_HEAP_HINT* hint; 00259 word32 idx = 0; 00260 00261 if (pHint == NULL || buf == NULL) { 00262 return BAD_FUNC_ARG; 00263 } 00264 00265 if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) { 00266 return BUFFER_E; /* not enough memory for structures */ 00267 } 00268 00269 /* check if hint has already been assigned */ 00270 if (*pHint == NULL) { 00271 heap = (WOLFSSL_HEAP*)buf; 00272 idx += sizeof(WOLFSSL_HEAP); 00273 hint = (WOLFSSL_HEAP_HINT*)(buf + idx); 00274 idx += sizeof(WOLFSSL_HEAP_HINT); 00275 00276 ret = wolfSSL_init_memory_heap(heap); 00277 if (ret != 0) { 00278 return ret; 00279 } 00280 00281 XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); 00282 hint->memory = heap; 00283 } 00284 else { 00285 #ifdef WOLFSSL_HEAP_TEST 00286 /* do not load in memory if test has been set */ 00287 if (heap == (void*)WOLFSSL_HEAP_TEST) { 00288 return 0; 00289 } 00290 #endif 00291 00292 hint = (WOLFSSL_HEAP_HINT*)(*pHint); 00293 heap = hint->memory; 00294 } 00295 00296 ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap); 00297 if (ret != 1) { 00298 WOLFSSL_MSG("Error partitioning memory"); 00299 return -1; 00300 } 00301 00302 /* determine what max applies too */ 00303 if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) { 00304 heap->maxIO = max; 00305 } 00306 else { /* general memory used in handshakes */ 00307 heap->maxHa = max; 00308 } 00309 00310 heap->flag |= flag; 00311 *pHint = hint; 00312 00313 (void)max; 00314 00315 return 0; 00316 } 00317 00318 int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag, 00319 WOLFSSL_HEAP* heap) 00320 { 00321 word32 ava = sz; 00322 byte* pt = buffer; 00323 int ret = 0; 00324 word32 memSz = (word32)sizeof(wc_Memory); 00325 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); 00326 00327 WOLFSSL_ENTER("wolfSSL_load_static_memory"); 00328 00329 if (buffer == NULL) { 00330 return BAD_FUNC_ARG; 00331 } 00332 00333 /* align pt */ 00334 while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { 00335 *pt = 0x00; 00336 pt++; 00337 ava--; 00338 } 00339 00340 #ifdef WOLFSSL_DEBUG_MEMORY 00341 printf("Allocated %d bytes for static memory @ %p\n", ava, pt); 00342 #endif 00343 00344 /* devide into chunks of memory and add them to available list */ 00345 while (ava >= (heap->sizeList[0] + padSz + memSz)) { 00346 int i; 00347 /* creating only IO buffers from memory passed in, max TLS is 16k */ 00348 if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { 00349 if ((ret = create_memory_buckets(pt, ava, 00350 WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { 00351 WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); 00352 return ret; 00353 } 00354 00355 /* check if no more room left for creating IO buffers */ 00356 if (ret == 0) { 00357 break; 00358 } 00359 00360 /* advance pointer in buffer for next buckets and keep track 00361 of how much memory is left available */ 00362 pt += ret; 00363 ava -= ret; 00364 } 00365 else { 00366 /* start at largest and move to smaller buckets */ 00367 for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { 00368 if ((heap->sizeList[i] + padSz + memSz) <= ava) { 00369 if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i], 00370 heap->distList[i], &(heap->ava[i]))) < 0) { 00371 WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); 00372 return ret; 00373 } 00374 00375 /* advance pointer in buffer for next buckets and keep track 00376 of how much memory is left available */ 00377 pt += ret; 00378 ava -= ret; 00379 } 00380 } 00381 } 00382 } 00383 00384 return 1; 00385 } 00386 00387 00388 /* returns the size of management memory needed for each bucket. 00389 * This is memory that is used to keep track of and align memory buckets. */ 00390 int wolfSSL_MemoryPaddingSz(void) 00391 { 00392 word32 memSz = (word32)sizeof(wc_Memory); 00393 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); 00394 return memSz + padSz; 00395 } 00396 00397 00398 /* Used to calculate memory size for optimum use with buckets. 00399 returns the suggested size rounded down to the nearest bucket. */ 00400 int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) 00401 { 00402 word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS}; 00403 word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST}; 00404 00405 word32 ava = sz; 00406 byte* pt = buffer; 00407 word32 memSz = (word32)sizeof(wc_Memory); 00408 word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); 00409 00410 WOLFSSL_ENTER("wolfSSL_static_size"); 00411 00412 if (buffer == NULL) { 00413 return BAD_FUNC_ARG; 00414 } 00415 00416 /* align pt */ 00417 while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { 00418 pt++; 00419 ava--; 00420 } 00421 00422 /* creating only IO buffers from memory passed in, max TLS is 16k */ 00423 if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { 00424 if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { 00425 return 0; /* not enough room for even one bucket */ 00426 } 00427 00428 ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); 00429 } 00430 else { 00431 int i, k; 00432 00433 if (ava < (bucketSz[0] + padSz + memSz)) { 00434 return 0; /* not enough room for even one bucket */ 00435 } 00436 00437 while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { 00438 /* start at largest and move to smaller buckets */ 00439 for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { 00440 for (k = distList[i]; k > 0; k--) { 00441 if ((bucketSz[i] + padSz + memSz) <= ava) { 00442 ava -= bucketSz[i] + padSz + memSz; 00443 } 00444 } 00445 } 00446 } 00447 } 00448 00449 return sz - ava; /* round down */ 00450 } 00451 00452 00453 int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) 00454 { 00455 WOLFSSL_MSG("Freeing fixed IO buffer"); 00456 00457 /* check if fixed buffer was set */ 00458 if (*io == NULL) { 00459 return 1; 00460 } 00461 00462 if (heap == NULL) { 00463 WOLFSSL_MSG("No heap to return fixed IO too"); 00464 } 00465 else { 00466 /* put IO buffer back into IO pool */ 00467 (*io)->next = heap->io; 00468 heap->io = *io; 00469 *io = NULL; 00470 } 00471 00472 return 1; 00473 } 00474 00475 00476 int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) 00477 { 00478 WOLFSSL_MSG("Setting fixed IO for SSL"); 00479 if (heap == NULL) { 00480 return MEMORY_E; 00481 } 00482 00483 *io = heap->io; 00484 00485 if (*io != NULL) { 00486 heap->io = (*io)->next; 00487 (*io)->next = NULL; 00488 } 00489 else { /* failed to grab an IO buffer */ 00490 return 0; 00491 } 00492 00493 return 1; 00494 } 00495 00496 00497 int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats) 00498 { 00499 word32 i; 00500 wc_Memory* pt; 00501 00502 XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS)); 00503 00504 stats->totalAlloc = heap->alloc; 00505 stats->totalFr = heap->frAlc; 00506 stats->curAlloc = stats->totalAlloc - stats->totalFr; 00507 stats->maxHa = heap->maxHa; 00508 stats->maxIO = heap->maxIO; 00509 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { 00510 stats->blockSz[i] = heap->sizeList[i]; 00511 for (pt = heap->ava[i]; pt != NULL; pt = pt->next) { 00512 stats->avaBlock[i] += 1; 00513 } 00514 } 00515 00516 for (pt = heap->io; pt != NULL; pt = pt->next) { 00517 stats->avaIO++; 00518 } 00519 00520 stats->flag = heap->flag; /* flag used */ 00521 00522 return 1; 00523 } 00524 00525 00526 #ifdef WOLFSSL_DEBUG_MEMORY 00527 void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line) 00528 #else 00529 void* wolfSSL_Malloc(size_t size, void* heap, int type) 00530 #endif 00531 { 00532 void* res = 0; 00533 wc_Memory* pt = NULL; 00534 int i; 00535 00536 /* check for testing heap hint was set */ 00537 #ifdef WOLFSSL_HEAP_TEST 00538 if (heap == (void*)WOLFSSL_HEAP_TEST) { 00539 return malloc(size); 00540 } 00541 #endif 00542 00543 /* if no heap hint then use dynamic memory*/ 00544 if (heap == NULL) { 00545 #ifdef WOLFSSL_HEAP_TEST 00546 /* allow using malloc for creating ctx and method */ 00547 if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || 00548 type == DYNAMIC_TYPE_CERT_MANAGER) { 00549 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n"); 00550 res = malloc(size); 00551 } 00552 else { 00553 WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n"); 00554 res = NULL; 00555 } 00556 #else 00557 #ifndef WOLFSSL_NO_MALLOC 00558 #ifdef FREERTOS 00559 res = pvPortMalloc(size); 00560 #else 00561 res = malloc(size); 00562 #endif 00563 #else 00564 WOLFSSL_MSG("No heap hint found to use and no malloc"); 00565 #ifdef WOLFSSL_DEBUG_MEMORY 00566 printf("ERROR: at %s:%d\n", func, line); 00567 #endif 00568 #endif /* WOLFSSL_NO_MALLOC */ 00569 #endif /* WOLFSSL_HEAP_TEST */ 00570 } 00571 else { 00572 WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; 00573 WOLFSSL_HEAP* mem = hint->memory; 00574 00575 if (wc_LockMutex(&(mem->memory_mutex)) != 0) { 00576 WOLFSSL_MSG("Bad memory_mutex lock"); 00577 return NULL; 00578 } 00579 00580 /* case of using fixed IO buffers */ 00581 if (mem->flag & WOLFMEM_IO_POOL_FIXED && 00582 (type == DYNAMIC_TYPE_OUT_BUFFER || 00583 type == DYNAMIC_TYPE_IN_BUFFER)) { 00584 if (type == DYNAMIC_TYPE_OUT_BUFFER) { 00585 pt = hint->outBuf; 00586 } 00587 if (type == DYNAMIC_TYPE_IN_BUFFER) { 00588 pt = hint->inBuf; 00589 } 00590 } 00591 else { 00592 /* check if using IO pool flag */ 00593 if (mem->flag & WOLFMEM_IO_POOL && 00594 (type == DYNAMIC_TYPE_OUT_BUFFER || 00595 type == DYNAMIC_TYPE_IN_BUFFER)) { 00596 if (mem->io != NULL) { 00597 pt = mem->io; 00598 mem->io = pt->next; 00599 } 00600 } 00601 00602 /* general static memory */ 00603 if (pt == NULL) { 00604 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { 00605 if ((word32)size < mem->sizeList[i]) { 00606 if (mem->ava[i] != NULL) { 00607 pt = mem->ava[i]; 00608 mem->ava[i] = pt->next; 00609 break; 00610 } 00611 } 00612 } 00613 } 00614 } 00615 00616 if (pt != NULL) { 00617 mem->inUse += pt->sz; 00618 mem->alloc += 1; 00619 res = pt->buffer; 00620 00621 #ifdef WOLFSSL_DEBUG_MEMORY 00622 printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); 00623 #endif 00624 00625 /* keep track of connection statistics if flag is set */ 00626 if (mem->flag & WOLFMEM_TRACK_STATS) { 00627 WOLFSSL_MEM_CONN_STATS* stats = hint->stats; 00628 if (stats != NULL) { 00629 stats->curMem += pt->sz; 00630 if (stats->peakMem < stats->curMem) { 00631 stats->peakMem = stats->curMem; 00632 } 00633 stats->curAlloc++; 00634 if (stats->peakAlloc < stats->curAlloc) { 00635 stats->peakAlloc = stats->curAlloc; 00636 } 00637 stats->totalAlloc++; 00638 } 00639 } 00640 } 00641 else { 00642 WOLFSSL_MSG("ERROR ran out of static memory"); 00643 #ifdef WOLFSSL_DEBUG_MEMORY 00644 printf("Looking for %lu bytes at %s:%d\n", size, func, line); 00645 #endif 00646 } 00647 00648 wc_UnLockMutex(&(mem->memory_mutex)); 00649 } 00650 00651 #ifdef WOLFSSL_MALLOC_CHECK 00652 if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) { 00653 WOLFSSL_MSG("ERROR memory is not alligned"); 00654 res = NULL; 00655 } 00656 #endif 00657 00658 00659 (void)i; 00660 (void)pt; 00661 (void)type; 00662 00663 return res; 00664 } 00665 00666 00667 #ifdef WOLFSSL_DEBUG_MEMORY 00668 void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line) 00669 #else 00670 void wolfSSL_Free(void *ptr, void* heap, int type) 00671 #endif 00672 { 00673 int i; 00674 wc_Memory* pt; 00675 00676 if (ptr) { 00677 /* check for testing heap hint was set */ 00678 #ifdef WOLFSSL_HEAP_TEST 00679 if (heap == (void*)WOLFSSL_HEAP_TEST) { 00680 return free(ptr); 00681 } 00682 #endif 00683 00684 if (heap == NULL) { 00685 #ifdef WOLFSSL_HEAP_TEST 00686 /* allow using malloc for creating ctx and method */ 00687 if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || 00688 type == DYNAMIC_TYPE_CERT_MANAGER) { 00689 WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n"); 00690 } 00691 else { 00692 WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n"); 00693 } 00694 #endif 00695 #ifndef WOLFSSL_NO_MALLOC 00696 #ifdef FREERTOS 00697 vPortFree(ptr); 00698 #else 00699 free(ptr); 00700 #endif 00701 #else 00702 WOLFSSL_MSG("Error trying to call free when turned off"); 00703 #endif /* WOLFSSL_NO_MALLOC */ 00704 } 00705 else { 00706 WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; 00707 WOLFSSL_HEAP* mem = hint->memory; 00708 word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); 00709 00710 /* get memory struct and add it to available list */ 00711 pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz); 00712 if (wc_LockMutex(&(mem->memory_mutex)) != 0) { 00713 WOLFSSL_MSG("Bad memory_mutex lock"); 00714 return; 00715 } 00716 00717 /* case of using fixed IO buffers */ 00718 if (mem->flag & WOLFMEM_IO_POOL_FIXED && 00719 (type == DYNAMIC_TYPE_OUT_BUFFER || 00720 type == DYNAMIC_TYPE_IN_BUFFER)) { 00721 /* fixed IO pools are free'd at the end of SSL lifetime 00722 using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */ 00723 } 00724 else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ && 00725 (type == DYNAMIC_TYPE_OUT_BUFFER || 00726 type == DYNAMIC_TYPE_IN_BUFFER)) { 00727 pt->next = mem->io; 00728 mem->io = pt; 00729 } 00730 else { /* general memory free */ 00731 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { 00732 if (pt->sz == mem->sizeList[i]) { 00733 pt->next = mem->ava[i]; 00734 mem->ava[i] = pt; 00735 break; 00736 } 00737 } 00738 } 00739 mem->inUse -= pt->sz; 00740 mem->frAlc += 1; 00741 00742 #ifdef WOLFSSL_DEBUG_MEMORY 00743 printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); 00744 #endif 00745 00746 /* keep track of connection statistics if flag is set */ 00747 if (mem->flag & WOLFMEM_TRACK_STATS) { 00748 WOLFSSL_MEM_CONN_STATS* stats = hint->stats; 00749 if (stats != NULL) { 00750 /* avoid under flow */ 00751 if (stats->curMem > pt->sz) { 00752 stats->curMem -= pt->sz; 00753 } 00754 else { 00755 stats->curMem = 0; 00756 } 00757 00758 if (stats->curAlloc > 0) { 00759 stats->curAlloc--; 00760 } 00761 stats->totalFr++; 00762 } 00763 } 00764 wc_UnLockMutex(&(mem->memory_mutex)); 00765 } 00766 } 00767 00768 (void)i; 00769 (void)pt; 00770 (void)type; 00771 } 00772 00773 #ifdef WOLFSSL_DEBUG_MEMORY 00774 void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line) 00775 #else 00776 void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) 00777 #endif 00778 { 00779 void* res = 0; 00780 wc_Memory* pt = NULL; 00781 word32 prvSz; 00782 int i; 00783 00784 /* check for testing heap hint was set */ 00785 #ifdef WOLFSSL_HEAP_TEST 00786 if (heap == (void*)WOLFSSL_HEAP_TEST) { 00787 return realloc(ptr, size); 00788 } 00789 #endif 00790 00791 if (heap == NULL) { 00792 #ifdef WOLFSSL_HEAP_TEST 00793 WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n"); 00794 #endif 00795 #ifndef WOLFSSL_NO_MALLOC 00796 res = realloc(ptr, size); 00797 #else 00798 WOLFSSL_MSG("NO heap found to use for realloc"); 00799 #endif /* WOLFSSL_NO_MALLOC */ 00800 } 00801 else { 00802 WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; 00803 WOLFSSL_HEAP* mem = hint->memory; 00804 word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); 00805 00806 if (wc_LockMutex(&(mem->memory_mutex)) != 0) { 00807 WOLFSSL_MSG("Bad memory_mutex lock"); 00808 return NULL; 00809 } 00810 00811 /* case of using fixed IO buffers or IO pool */ 00812 if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED)) 00813 && (type == DYNAMIC_TYPE_OUT_BUFFER || 00814 type == DYNAMIC_TYPE_IN_BUFFER)) { 00815 /* no realloc, is fixed size */ 00816 pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory)); 00817 if (pt->sz < size) { 00818 WOLFSSL_MSG("Error IO memory was not large enough"); 00819 res = NULL; /* return NULL in error case */ 00820 } 00821 res = pt->buffer; 00822 } 00823 else { 00824 /* general memory */ 00825 for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { 00826 if ((word32)size < mem->sizeList[i]) { 00827 if (mem->ava[i] != NULL) { 00828 pt = mem->ava[i]; 00829 mem->ava[i] = pt->next; 00830 break; 00831 } 00832 } 00833 } 00834 00835 if (pt != NULL && res == NULL) { 00836 res = pt->buffer; 00837 00838 /* copy over original information and free ptr */ 00839 prvSz = ((wc_Memory*)((byte*)ptr - padSz - 00840 sizeof(wc_Memory)))->sz; 00841 prvSz = (prvSz > pt->sz)? pt->sz: prvSz; 00842 XMEMCPY(pt->buffer, ptr, prvSz); 00843 mem->inUse += pt->sz; 00844 mem->alloc += 1; 00845 00846 /* free memory that was previously being used */ 00847 wc_UnLockMutex(&(mem->memory_mutex)); 00848 wolfSSL_Free(ptr, heap, type 00849 #ifdef WOLFSSL_DEBUG_MEMORY 00850 , func, line 00851 #endif 00852 ); 00853 if (wc_LockMutex(&(mem->memory_mutex)) != 0) { 00854 WOLFSSL_MSG("Bad memory_mutex lock"); 00855 return NULL; 00856 } 00857 } 00858 } 00859 wc_UnLockMutex(&(mem->memory_mutex)); 00860 } 00861 00862 #ifdef WOLFSSL_MALLOC_CHECK 00863 if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) { 00864 WOLFSSL_MSG("ERROR memory is not alligned"); 00865 res = NULL; 00866 } 00867 #endif 00868 00869 (void)i; 00870 (void)pt; 00871 (void)type; 00872 00873 return res; 00874 } 00875 #endif /* WOLFSSL_STATIC_MEMORY */ 00876 00877 #endif /* USE_WOLFSSL_MEMORY */ 00878 00879 00880 #ifdef HAVE_IO_POOL 00881 00882 /* Example for user io pool, shared build may need definitions in lib proper */ 00883 00884 #include <wolfssl/wolfcrypt/types.h> 00885 #include <stdlib.h> 00886 00887 #ifndef HAVE_THREAD_LS 00888 #error "Oops, simple I/O pool example needs thread local storage" 00889 #endif 00890 00891 00892 /* allow simple per thread in and out pools */ 00893 /* use 17k size since max record size is 16k plus overhead */ 00894 static THREAD_LS_T byte pool_in[17*1024]; 00895 static THREAD_LS_T byte pool_out[17*1024]; 00896 00897 00898 void* XMALLOC(size_t n, void* heap, int type) 00899 { 00900 (void)heap; 00901 00902 if (type == DYNAMIC_TYPE_IN_BUFFER) { 00903 if (n < sizeof(pool_in)) 00904 return pool_in; 00905 else 00906 return NULL; 00907 } 00908 00909 if (type == DYNAMIC_TYPE_OUT_BUFFER) { 00910 if (n < sizeof(pool_out)) 00911 return pool_out; 00912 else 00913 return NULL; 00914 } 00915 00916 return malloc(n); 00917 } 00918 00919 void* XREALLOC(void *p, size_t n, void* heap, int type) 00920 { 00921 (void)heap; 00922 00923 if (type == DYNAMIC_TYPE_IN_BUFFER) { 00924 if (n < sizeof(pool_in)) 00925 return pool_in; 00926 else 00927 return NULL; 00928 } 00929 00930 if (type == DYNAMIC_TYPE_OUT_BUFFER) { 00931 if (n < sizeof(pool_out)) 00932 return pool_out; 00933 else 00934 return NULL; 00935 } 00936 00937 return realloc(p, n); 00938 } 00939 00940 void XFREE(void *p, void* heap, int type) 00941 { 00942 (void)heap; 00943 00944 if (type == DYNAMIC_TYPE_IN_BUFFER) 00945 return; /* do nothing, static pool */ 00946 00947 if (type == DYNAMIC_TYPE_OUT_BUFFER) 00948 return; /* do nothing, static pool */ 00949 00950 free(p); 00951 } 00952 00953 #endif /* HAVE_IO_POOL */ 00954 00955
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2