1 /* 2 * Buffer-based memory allocator 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 * 7 * This file is provided under the Apache License 2.0, or the 8 * GNU General Public License v2.0 or later. 9 * 10 * ********** 11 * Apache License 2.0: 12 * 13 * Licensed under the Apache License, Version 2.0 (the "License"); you may 14 * not use this file except in compliance with the License. 15 * You may obtain a copy of the License at 16 * 17 * http://www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, software 20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 * See the License for the specific language governing permissions and 23 * limitations under the License. 24 * 25 * ********** 26 * 27 * ********** 28 * GNU General Public License v2.0 or later: 29 * 30 * This program is free software; you can redistribute it and/or modify 31 * it under the terms of the GNU General Public License as published by 32 * the Free Software Foundation; either version 2 of the License, or 33 * (at your option) any later version. 34 * 35 * This program is distributed in the hope that it will be useful, 36 * but WITHOUT ANY WARRANTY; without even the implied warranty of 37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 * GNU General Public License for more details. 39 * 40 * You should have received a copy of the GNU General Public License along 41 * with this program; if not, write to the Free Software Foundation, Inc., 42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 43 * 44 * ********** 45 */ 46 47 #if !defined(MBEDTLS_CONFIG_FILE) 48 #include "mbedtls/config.h" 49 #else 50 #include MBEDTLS_CONFIG_FILE 51 #endif 52 53 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) 54 #include "mbedtls/memory_buffer_alloc.h" 55 56 /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C 57 is dependent upon MBEDTLS_PLATFORM_C */ 58 #include "mbedtls/platform.h" 59 #include "mbedtls/platform_util.h" 60 61 #include <string.h> 62 63 #if defined(MBEDTLS_MEMORY_BACKTRACE) 64 #include <execinfo.h> 65 #endif 66 67 #if defined(MBEDTLS_THREADING_C) 68 #include "mbedtls/threading.h" 69 #endif 70 71 #define MAGIC1 0xFF00AA55 72 #define MAGIC2 0xEE119966 73 #define MAX_BT 20 74 75 typedef struct _memory_header memory_header; 76 struct _memory_header 77 { 78 size_t magic1; 79 size_t size; 80 size_t alloc; 81 memory_header *prev; 82 memory_header *next; 83 memory_header *prev_free; 84 memory_header *next_free; 85 #if defined(MBEDTLS_MEMORY_BACKTRACE) 86 char **trace; 87 size_t trace_count; 88 #endif 89 size_t magic2; 90 }; 91 92 typedef struct 93 { 94 unsigned char *buf; 95 size_t len; 96 memory_header *first; 97 memory_header *first_free; 98 int verify; 99 #if defined(MBEDTLS_MEMORY_DEBUG) 100 size_t alloc_count; 101 size_t free_count; 102 size_t total_used; 103 size_t maximum_used; 104 size_t header_count; 105 size_t maximum_header_count; 106 #endif 107 #if defined(MBEDTLS_THREADING_C) 108 mbedtls_threading_mutex_t mutex; 109 #endif 110 } 111 buffer_alloc_ctx; 112 113 static buffer_alloc_ctx heap; 114 115 #if defined(MBEDTLS_MEMORY_DEBUG) 116 static void debug_header( memory_header *hdr ) 117 { 118 #if defined(MBEDTLS_MEMORY_BACKTRACE) 119 size_t i; 120 #endif 121 122 mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " 123 "ALLOC(%zu), SIZE(%10zu)\n", 124 (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, 125 hdr->alloc, hdr->size ); 126 mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", 127 (size_t) hdr->prev_free, (size_t) hdr->next_free ); 128 129 #if defined(MBEDTLS_MEMORY_BACKTRACE) 130 mbedtls_fprintf( stderr, "TRACE: \n" ); 131 for( i = 0; i < hdr->trace_count; i++ ) 132 mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); 133 mbedtls_fprintf( stderr, "\n" ); 134 #endif 135 } 136 137 static void debug_chain( void ) 138 { 139 memory_header *cur = heap.first; 140 141 mbedtls_fprintf( stderr, "\nBlock list\n" ); 142 while( cur != NULL ) 143 { 144 debug_header( cur ); 145 cur = cur->next; 146 } 147 148 mbedtls_fprintf( stderr, "Free list\n" ); 149 cur = heap.first_free; 150 151 while( cur != NULL ) 152 { 153 debug_header( cur ); 154 cur = cur->next_free; 155 } 156 } 157 #endif /* MBEDTLS_MEMORY_DEBUG */ 158 159 static int verify_header( memory_header *hdr ) 160 { 161 if( hdr->magic1 != MAGIC1 ) 162 { 163 #if defined(MBEDTLS_MEMORY_DEBUG) 164 mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); 165 #endif 166 return( 1 ); 167 } 168 169 if( hdr->magic2 != MAGIC2 ) 170 { 171 #if defined(MBEDTLS_MEMORY_DEBUG) 172 mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); 173 #endif 174 return( 1 ); 175 } 176 177 if( hdr->alloc > 1 ) 178 { 179 #if defined(MBEDTLS_MEMORY_DEBUG) 180 mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); 181 #endif 182 return( 1 ); 183 } 184 185 if( hdr->prev != NULL && hdr->prev == hdr->next ) 186 { 187 #if defined(MBEDTLS_MEMORY_DEBUG) 188 mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); 189 #endif 190 return( 1 ); 191 } 192 193 if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) 194 { 195 #if defined(MBEDTLS_MEMORY_DEBUG) 196 mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); 197 #endif 198 return( 1 ); 199 } 200 201 return( 0 ); 202 } 203 204 static int verify_chain( void ) 205 { 206 memory_header *prv = heap.first, *cur; 207 208 if( prv == NULL || verify_header( prv ) != 0 ) 209 { 210 #if defined(MBEDTLS_MEMORY_DEBUG) 211 mbedtls_fprintf( stderr, "FATAL: verification of first header " 212 "failed\n" ); 213 #endif 214 return( 1 ); 215 } 216 217 if( heap.first->prev != NULL ) 218 { 219 #if defined(MBEDTLS_MEMORY_DEBUG) 220 mbedtls_fprintf( stderr, "FATAL: verification failed: " 221 "first->prev != NULL\n" ); 222 #endif 223 return( 1 ); 224 } 225 226 cur = heap.first->next; 227 228 while( cur != NULL ) 229 { 230 if( verify_header( cur ) != 0 ) 231 { 232 #if defined(MBEDTLS_MEMORY_DEBUG) 233 mbedtls_fprintf( stderr, "FATAL: verification of header " 234 "failed\n" ); 235 #endif 236 return( 1 ); 237 } 238 239 if( cur->prev != prv ) 240 { 241 #if defined(MBEDTLS_MEMORY_DEBUG) 242 mbedtls_fprintf( stderr, "FATAL: verification failed: " 243 "cur->prev != prv\n" ); 244 #endif 245 return( 1 ); 246 } 247 248 prv = cur; 249 cur = cur->next; 250 } 251 252 return( 0 ); 253 } 254 255 static void *buffer_alloc_calloc( size_t n, size_t size ) 256 { 257 memory_header *new, *cur = heap.first_free; 258 unsigned char *p; 259 void *ret; 260 size_t original_len, len; 261 #if defined(MBEDTLS_MEMORY_BACKTRACE) 262 void *trace_buffer[MAX_BT]; 263 size_t trace_cnt; 264 #endif 265 266 if( heap.buf == NULL || heap.first == NULL ) 267 return( NULL ); 268 269 original_len = len = n * size; 270 271 if( n == 0 || size == 0 || len / n != size ) 272 return( NULL ); 273 else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) 274 return( NULL ); 275 276 if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) 277 { 278 len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; 279 len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; 280 } 281 282 // Find block that fits 283 // 284 while( cur != NULL ) 285 { 286 if( cur->size >= len ) 287 break; 288 289 cur = cur->next_free; 290 } 291 292 if( cur == NULL ) 293 return( NULL ); 294 295 if( cur->alloc != 0 ) 296 { 297 #if defined(MBEDTLS_MEMORY_DEBUG) 298 mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " 299 "data\n" ); 300 #endif 301 mbedtls_exit( 1 ); 302 } 303 304 #if defined(MBEDTLS_MEMORY_DEBUG) 305 heap.alloc_count++; 306 #endif 307 308 // Found location, split block if > memory_header + 4 room left 309 // 310 if( cur->size - len < sizeof(memory_header) + 311 MBEDTLS_MEMORY_ALIGN_MULTIPLE ) 312 { 313 cur->alloc = 1; 314 315 // Remove from free_list 316 // 317 if( cur->prev_free != NULL ) 318 cur->prev_free->next_free = cur->next_free; 319 else 320 heap.first_free = cur->next_free; 321 322 if( cur->next_free != NULL ) 323 cur->next_free->prev_free = cur->prev_free; 324 325 cur->prev_free = NULL; 326 cur->next_free = NULL; 327 328 #if defined(MBEDTLS_MEMORY_DEBUG) 329 heap.total_used += cur->size; 330 if( heap.total_used > heap.maximum_used ) 331 heap.maximum_used = heap.total_used; 332 #endif 333 #if defined(MBEDTLS_MEMORY_BACKTRACE) 334 trace_cnt = backtrace( trace_buffer, MAX_BT ); 335 cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); 336 cur->trace_count = trace_cnt; 337 #endif 338 339 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) 340 mbedtls_exit( 1 ); 341 342 ret = (unsigned char *) cur + sizeof( memory_header ); 343 memset( ret, 0, original_len ); 344 345 return( ret ); 346 } 347 348 p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; 349 new = (memory_header *) p; 350 351 new->size = cur->size - len - sizeof(memory_header); 352 new->alloc = 0; 353 new->prev = cur; 354 new->next = cur->next; 355 #if defined(MBEDTLS_MEMORY_BACKTRACE) 356 new->trace = NULL; 357 new->trace_count = 0; 358 #endif 359 new->magic1 = MAGIC1; 360 new->magic2 = MAGIC2; 361 362 if( new->next != NULL ) 363 new->next->prev = new; 364 365 // Replace cur with new in free_list 366 // 367 new->prev_free = cur->prev_free; 368 new->next_free = cur->next_free; 369 if( new->prev_free != NULL ) 370 new->prev_free->next_free = new; 371 else 372 heap.first_free = new; 373 374 if( new->next_free != NULL ) 375 new->next_free->prev_free = new; 376 377 cur->alloc = 1; 378 cur->size = len; 379 cur->next = new; 380 cur->prev_free = NULL; 381 cur->next_free = NULL; 382 383 #if defined(MBEDTLS_MEMORY_DEBUG) 384 heap.header_count++; 385 if( heap.header_count > heap.maximum_header_count ) 386 heap.maximum_header_count = heap.header_count; 387 heap.total_used += cur->size; 388 if( heap.total_used > heap.maximum_used ) 389 heap.maximum_used = heap.total_used; 390 #endif 391 #if defined(MBEDTLS_MEMORY_BACKTRACE) 392 trace_cnt = backtrace( trace_buffer, MAX_BT ); 393 cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); 394 cur->trace_count = trace_cnt; 395 #endif 396 397 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) 398 mbedtls_exit( 1 ); 399 400 ret = (unsigned char *) cur + sizeof( memory_header ); 401 memset( ret, 0, original_len ); 402 403 return( ret ); 404 } 405 406 static void buffer_alloc_free( void *ptr ) 407 { 408 memory_header *hdr, *old = NULL; 409 unsigned char *p = (unsigned char *) ptr; 410 411 if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) 412 return; 413 414 if( p < heap.buf || p >= heap.buf + heap.len ) 415 { 416 #if defined(MBEDTLS_MEMORY_DEBUG) 417 mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " 418 "space\n" ); 419 #endif 420 mbedtls_exit( 1 ); 421 } 422 423 p -= sizeof(memory_header); 424 hdr = (memory_header *) p; 425 426 if( verify_header( hdr ) != 0 ) 427 mbedtls_exit( 1 ); 428 429 if( hdr->alloc != 1 ) 430 { 431 #if defined(MBEDTLS_MEMORY_DEBUG) 432 mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " 433 "data\n" ); 434 #endif 435 mbedtls_exit( 1 ); 436 } 437 438 hdr->alloc = 0; 439 440 #if defined(MBEDTLS_MEMORY_DEBUG) 441 heap.free_count++; 442 heap.total_used -= hdr->size; 443 #endif 444 445 #if defined(MBEDTLS_MEMORY_BACKTRACE) 446 free( hdr->trace ); 447 hdr->trace = NULL; 448 hdr->trace_count = 0; 449 #endif 450 451 // Regroup with block before 452 // 453 if( hdr->prev != NULL && hdr->prev->alloc == 0 ) 454 { 455 #if defined(MBEDTLS_MEMORY_DEBUG) 456 heap.header_count--; 457 #endif 458 hdr->prev->size += sizeof(memory_header) + hdr->size; 459 hdr->prev->next = hdr->next; 460 old = hdr; 461 hdr = hdr->prev; 462 463 if( hdr->next != NULL ) 464 hdr->next->prev = hdr; 465 466 memset( old, 0, sizeof(memory_header) ); 467 } 468 469 // Regroup with block after 470 // 471 if( hdr->next != NULL && hdr->next->alloc == 0 ) 472 { 473 #if defined(MBEDTLS_MEMORY_DEBUG) 474 heap.header_count--; 475 #endif 476 hdr->size += sizeof(memory_header) + hdr->next->size; 477 old = hdr->next; 478 hdr->next = hdr->next->next; 479 480 if( hdr->prev_free != NULL || hdr->next_free != NULL ) 481 { 482 if( hdr->prev_free != NULL ) 483 hdr->prev_free->next_free = hdr->next_free; 484 else 485 heap.first_free = hdr->next_free; 486 487 if( hdr->next_free != NULL ) 488 hdr->next_free->prev_free = hdr->prev_free; 489 } 490 491 hdr->prev_free = old->prev_free; 492 hdr->next_free = old->next_free; 493 494 if( hdr->prev_free != NULL ) 495 hdr->prev_free->next_free = hdr; 496 else 497 heap.first_free = hdr; 498 499 if( hdr->next_free != NULL ) 500 hdr->next_free->prev_free = hdr; 501 502 if( hdr->next != NULL ) 503 hdr->next->prev = hdr; 504 505 memset( old, 0, sizeof(memory_header) ); 506 } 507 508 // Prepend to free_list if we have not merged 509 // (Does not have to stay in same order as prev / next list) 510 // 511 if( old == NULL ) 512 { 513 hdr->next_free = heap.first_free; 514 if( heap.first_free != NULL ) 515 heap.first_free->prev_free = hdr; 516 heap.first_free = hdr; 517 } 518 519 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) 520 mbedtls_exit( 1 ); 521 } 522 523 void mbedtls_memory_buffer_set_verify( int verify ) 524 { 525 heap.verify = verify; 526 } 527 528 int mbedtls_memory_buffer_alloc_verify( void ) 529 { 530 return verify_chain(); 531 } 532 533 #if defined(MBEDTLS_MEMORY_DEBUG) 534 void mbedtls_memory_buffer_alloc_status( void ) 535 { 536 mbedtls_fprintf( stderr, 537 "Current use: %zu blocks / %zu bytes, max: %zu blocks / " 538 "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", 539 heap.header_count, heap.total_used, 540 heap.maximum_header_count, heap.maximum_used, 541 heap.maximum_header_count * sizeof( memory_header ) 542 + heap.maximum_used, 543 heap.alloc_count, heap.free_count ); 544 545 if( heap.first->next == NULL ) 546 { 547 mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); 548 } 549 else 550 { 551 mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); 552 debug_chain(); 553 } 554 } 555 556 void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) 557 { 558 *max_used = heap.maximum_used; 559 *max_blocks = heap.maximum_header_count; 560 } 561 562 void mbedtls_memory_buffer_alloc_max_reset( void ) 563 { 564 heap.maximum_used = 0; 565 heap.maximum_header_count = 0; 566 } 567 568 void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) 569 { 570 *cur_used = heap.total_used; 571 *cur_blocks = heap.header_count; 572 } 573 #endif /* MBEDTLS_MEMORY_DEBUG */ 574 575 #if defined(MBEDTLS_THREADING_C) 576 static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) 577 { 578 void *buf; 579 if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) 580 return( NULL ); 581 buf = buffer_alloc_calloc( n, size ); 582 if( mbedtls_mutex_unlock( &heap.mutex ) ) 583 return( NULL ); 584 return( buf ); 585 } 586 587 static void buffer_alloc_free_mutexed( void *ptr ) 588 { 589 /* We have to good option here, but corrupting the heap seems 590 * worse than loosing memory. */ 591 if( mbedtls_mutex_lock( &heap.mutex ) ) 592 return; 593 buffer_alloc_free( ptr ); 594 (void) mbedtls_mutex_unlock( &heap.mutex ); 595 } 596 #endif /* MBEDTLS_THREADING_C */ 597 598 void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) 599 { 600 memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); 601 602 #if defined(MBEDTLS_THREADING_C) 603 mbedtls_mutex_init( &heap.mutex ); 604 mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, 605 buffer_alloc_free_mutexed ); 606 #else 607 mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); 608 #endif 609 610 if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) 611 return; 612 else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) 613 { 614 /* Adjust len first since buf is used in the computation */ 615 len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE 616 - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; 617 buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE 618 - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; 619 } 620 621 memset( buf, 0, len ); 622 623 heap.buf = buf; 624 heap.len = len; 625 626 heap.first = (memory_header *)buf; 627 heap.first->size = len - sizeof( memory_header ); 628 heap.first->magic1 = MAGIC1; 629 heap.first->magic2 = MAGIC2; 630 heap.first_free = heap.first; 631 } 632 633 void mbedtls_memory_buffer_alloc_free( void ) 634 { 635 #if defined(MBEDTLS_THREADING_C) 636 mbedtls_mutex_free( &heap.mutex ); 637 #endif 638 mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); 639 } 640 641 #if defined(MBEDTLS_SELF_TEST) 642 static int check_pointer( void *p ) 643 { 644 if( p == NULL ) 645 return( -1 ); 646 647 if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) 648 return( -1 ); 649 650 return( 0 ); 651 } 652 653 static int check_all_free( void ) 654 { 655 if( 656 #if defined(MBEDTLS_MEMORY_DEBUG) 657 heap.total_used != 0 || 658 #endif 659 heap.first != heap.first_free || 660 (void *) heap.first != (void *) heap.buf ) 661 { 662 return( -1 ); 663 } 664 665 return( 0 ); 666 } 667 668 #define TEST_ASSERT( condition ) \ 669 if( ! (condition) ) \ 670 { \ 671 if( verbose != 0 ) \ 672 mbedtls_printf( "failed\n" ); \ 673 \ 674 ret = 1; \ 675 goto cleanup; \ 676 } 677 678 int mbedtls_memory_buffer_alloc_self_test( int verbose ) 679 { 680 unsigned char buf[1024]; 681 unsigned char *p, *q, *r, *end; 682 int ret = 0; 683 684 if( verbose != 0 ) 685 mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); 686 687 mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); 688 689 p = mbedtls_calloc( 1, 1 ); 690 q = mbedtls_calloc( 1, 128 ); 691 r = mbedtls_calloc( 1, 16 ); 692 693 TEST_ASSERT( check_pointer( p ) == 0 && 694 check_pointer( q ) == 0 && 695 check_pointer( r ) == 0 ); 696 697 mbedtls_free( r ); 698 mbedtls_free( q ); 699 mbedtls_free( p ); 700 701 TEST_ASSERT( check_all_free( ) == 0 ); 702 703 /* Memorize end to compare with the next test */ 704 end = heap.buf + heap.len; 705 706 mbedtls_memory_buffer_alloc_free( ); 707 708 if( verbose != 0 ) 709 mbedtls_printf( "passed\n" ); 710 711 if( verbose != 0 ) 712 mbedtls_printf( " MBA test #2 (buf not aligned): " ); 713 714 mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); 715 716 TEST_ASSERT( heap.buf + heap.len == end ); 717 718 p = mbedtls_calloc( 1, 1 ); 719 q = mbedtls_calloc( 1, 128 ); 720 r = mbedtls_calloc( 1, 16 ); 721 722 TEST_ASSERT( check_pointer( p ) == 0 && 723 check_pointer( q ) == 0 && 724 check_pointer( r ) == 0 ); 725 726 mbedtls_free( r ); 727 mbedtls_free( q ); 728 mbedtls_free( p ); 729 730 TEST_ASSERT( check_all_free( ) == 0 ); 731 732 mbedtls_memory_buffer_alloc_free( ); 733 734 if( verbose != 0 ) 735 mbedtls_printf( "passed\n" ); 736 737 if( verbose != 0 ) 738 mbedtls_printf( " MBA test #3 (full): " ); 739 740 mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); 741 742 p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); 743 744 TEST_ASSERT( check_pointer( p ) == 0 ); 745 TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); 746 747 mbedtls_free( p ); 748 749 p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); 750 q = mbedtls_calloc( 1, 16 ); 751 752 TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); 753 TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); 754 755 mbedtls_free( q ); 756 757 TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); 758 759 mbedtls_free( p ); 760 761 TEST_ASSERT( check_all_free( ) == 0 ); 762 763 mbedtls_memory_buffer_alloc_free( ); 764 765 if( verbose != 0 ) 766 mbedtls_printf( "passed\n" ); 767 768 cleanup: 769 mbedtls_memory_buffer_alloc_free( ); 770 771 return( ret ); 772 } 773 #endif /* MBEDTLS_SELF_TEST */ 774 775 #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ 776