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)
debug_header(memory_header * hdr)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
debug_chain(void)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
verify_header(memory_header * hdr)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
verify_chain(void)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
buffer_alloc_calloc(size_t n,size_t size)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
buffer_alloc_free(void * ptr)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
mbedtls_memory_buffer_set_verify(int verify)523 void mbedtls_memory_buffer_set_verify( int verify )
524 {
525 heap.verify = verify;
526 }
527
mbedtls_memory_buffer_alloc_verify(void)528 int mbedtls_memory_buffer_alloc_verify( void )
529 {
530 return verify_chain();
531 }
532
533 #if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_memory_buffer_alloc_status(void)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
mbedtls_memory_buffer_alloc_max_get(size_t * max_used,size_t * max_blocks)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
mbedtls_memory_buffer_alloc_max_reset(void)562 void mbedtls_memory_buffer_alloc_max_reset( void )
563 {
564 heap.maximum_used = 0;
565 heap.maximum_header_count = 0;
566 }
567
mbedtls_memory_buffer_alloc_cur_get(size_t * cur_used,size_t * cur_blocks)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)
buffer_alloc_calloc_mutexed(size_t n,size_t size)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
buffer_alloc_free_mutexed(void * ptr)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
mbedtls_memory_buffer_alloc_init(unsigned char * buf,size_t len)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
mbedtls_memory_buffer_alloc_free(void)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)
check_pointer(void * p)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
check_all_free(void)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
mbedtls_memory_buffer_alloc_self_test(int verbose)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