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