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