blob: 79b0a8b8fa975b6c960702c7a84b1dfbe2654bdc [file] [log] [blame]
Paul Bakker6e339b52013-07-03 13:37:05 +02001/*
2 * Buffer-based memory allocator
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker6e339b52013-07-03 13:37:05 +02006 */
7
Gilles Peskinedb09ef62020-06-03 01:43:33 +02008#include "common.h"
Paul Bakker6e339b52013-07-03 13:37:05 +02009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020010#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000011#include "mbedtls/memory_buffer_alloc.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020013/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
14 is dependent upon MBEDTLS_PLATFORM_C */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000015#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050016#include "mbedtls/platform_util.h"
Rich Evansd08a6052015-02-12 12:17:10 +000017
Paul Bakker6e339b52013-07-03 13:37:05 +020018#include <string.h>
19
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020020#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020021#include <execinfo.h>
22#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020024#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000025#include "mbedtls/threading.h"
Paul Bakker1337aff2013-09-29 14:45:34 +020026#endif
27
Paul Bakker6e339b52013-07-03 13:37:05 +020028#define MAGIC1 0xFF00AA55
29#define MAGIC2 0xEE119966
30#define MAX_BT 20
31
32typedef struct _memory_header memory_header;
Gilles Peskine449bd832023-01-11 14:50:10 +010033struct _memory_header {
Paul Bakker6e339b52013-07-03 13:37:05 +020034 size_t magic1;
35 size_t size;
36 size_t alloc;
37 memory_header *prev;
38 memory_header *next;
Paul Bakker1ef120f2013-07-03 17:20:39 +020039 memory_header *prev_free;
40 memory_header *next_free;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020042 char **trace;
43 size_t trace_count;
44#endif
45 size_t magic2;
46};
47
Gilles Peskine449bd832023-01-11 14:50:10 +010048typedef struct {
Paul Bakker6e339b52013-07-03 13:37:05 +020049 unsigned char *buf;
50 size_t len;
51 memory_header *first;
Paul Bakker1ef120f2013-07-03 17:20:39 +020052 memory_header *first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +020053 int verify;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +020055 size_t alloc_count;
Paul Bakker891998e2013-07-03 14:45:05 +020056 size_t free_count;
57 size_t total_used;
58 size_t maximum_used;
59 size_t header_count;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +010060 size_t maximum_header_count;
Paul Bakker891998e2013-07-03 14:45:05 +020061#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#if defined(MBEDTLS_THREADING_C)
63 mbedtls_threading_mutex_t mutex;
Paul Bakker1337aff2013-09-29 14:45:34 +020064#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020065}
66buffer_alloc_ctx;
67
68static buffer_alloc_ctx heap;
69
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +010071static void debug_header(memory_header *hdr)
Paul Bakker6e339b52013-07-03 13:37:05 +020072{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020074 size_t i;
75#endif
76
Gilles Peskine449bd832023-01-11 14:50:10 +010077 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);
Paul Bakker6e339b52013-07-03 13:37:05 +020083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084#if defined(MBEDTLS_MEMORY_BACKTRACE)
Gilles Peskine449bd832023-01-11 14:50:10 +010085 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");
Paul Bakker6e339b52013-07-03 13:37:05 +020090#endif
91}
92
Gilles Peskine449bd832023-01-11 14:50:10 +010093static void debug_chain(void)
Paul Bakker6e339b52013-07-03 13:37:05 +020094{
95 memory_header *cur = heap.first;
96
Gilles Peskine449bd832023-01-11 14:50:10 +010097 mbedtls_fprintf(stderr, "\nBlock list\n");
98 while (cur != NULL) {
99 debug_header(cur);
Paul Bakker6e339b52013-07-03 13:37:05 +0200100 cur = cur->next;
101 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200102
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 mbedtls_fprintf(stderr, "Free list\n");
Paul Bakker1ef120f2013-07-03 17:20:39 +0200104 cur = heap.first_free;
105
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 while (cur != NULL) {
107 debug_header(cur);
Paul Bakker1ef120f2013-07-03 17:20:39 +0200108 cur = cur->next_free;
109 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200110}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111#endif /* MBEDTLS_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200112
Gilles Peskine449bd832023-01-11 14:50:10 +0100113static int verify_header(memory_header *hdr)
Paul Bakker6e339b52013-07-03 13:37:05 +0200114{
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 if (hdr->magic1 != MAGIC1) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 mbedtls_fprintf(stderr, "FATAL: MAGIC1 mismatch\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200118#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200120 }
121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 if (hdr->magic2 != MAGIC2) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100124 mbedtls_fprintf(stderr, "FATAL: MAGIC2 mismatch\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200125#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200127 }
128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 if (hdr->alloc > 1) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 mbedtls_fprintf(stderr, "FATAL: alloc has illegal value\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200132#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200134 }
135
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 if (hdr->prev != NULL && hdr->prev == hdr->next) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 mbedtls_fprintf(stderr, "FATAL: prev == next\n");
Paul Bakker1ef120f2013-07-03 17:20:39 +0200139#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 return 1;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200141 }
142
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 mbedtls_fprintf(stderr, "FATAL: prev_free == next_free\n");
Paul Bakker1ef120f2013-07-03 17:20:39 +0200146#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 return 1;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200148 }
149
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 return 0;
Paul Bakker6e339b52013-07-03 13:37:05 +0200151}
152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153static int verify_chain(void)
Paul Bakker6e339b52013-07-03 13:37:05 +0200154{
Andres AG9cf1f962017-01-30 14:34:25 +0000155 memory_header *prv = heap.first, *cur;
Paul Bakker6e339b52013-07-03 13:37:05 +0200156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 if (prv == NULL || verify_header(prv) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 mbedtls_fprintf(stderr, "FATAL: verification of first header "
160 "failed\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200161#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200163 }
164
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 if (heap.first->prev != NULL) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 mbedtls_fprintf(stderr, "FATAL: verification failed: "
168 "first->prev != NULL\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200169#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200171 }
172
Andres AG9cf1f962017-01-30 14:34:25 +0000173 cur = heap.first->next;
174
Gilles Peskine449bd832023-01-11 14:50:10 +0100175 while (cur != NULL) {
176 if (verify_header(cur) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 mbedtls_fprintf(stderr, "FATAL: verification of header "
179 "failed\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200180#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100181 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200182 }
183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 if (cur->prev != prv) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 mbedtls_fprintf(stderr, "FATAL: verification failed: "
187 "cur->prev != prv\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200188#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 return 1;
Paul Bakker6e339b52013-07-03 13:37:05 +0200190 }
191
192 prv = cur;
193 cur = cur->next;
194 }
195
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 return 0;
Paul Bakker6e339b52013-07-03 13:37:05 +0200197}
198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199static void *buffer_alloc_calloc(size_t n, size_t size)
Paul Bakker6e339b52013-07-03 13:37:05 +0200200{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200201 memory_header *new, *cur = heap.first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200202 unsigned char *p;
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200203 void *ret;
204 size_t original_len, len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200206 void *trace_buffer[MAX_BT];
207 size_t trace_cnt;
208#endif
209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if (heap.buf == NULL || heap.first == NULL) {
211 return NULL;
212 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200213
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200214 original_len = len = n * size;
215
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 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 }
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
224 len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Paul Bakker6e339b52013-07-03 13:37:05 +0200225 }
226
227 // Find block that fits
228 //
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 while (cur != NULL) {
230 if (cur->size >= len) {
Paul Bakker6e339b52013-07-03 13:37:05 +0200231 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200233
Paul Bakker1ef120f2013-07-03 17:20:39 +0200234 cur = cur->next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200235 }
236
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 if (cur == NULL) {
238 return NULL;
239 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200240
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 if (cur->alloc != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 mbedtls_fprintf(stderr, "FATAL: block in free_list but allocated "
244 "data\n");
Paul Bakker1ef120f2013-07-03 17:20:39 +0200245#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 mbedtls_exit(1);
Paul Bakker1ef120f2013-07-03 17:20:39 +0200247 }
248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard6c967b92015-05-27 20:18:39 +0200250 heap.alloc_count++;
Paul Bakker891998e2013-07-03 14:45:05 +0200251#endif
252
Paul Bakker6e339b52013-07-03 13:37:05 +0200253 // Found location, split block if > memory_header + 4 room left
254 //
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 if (cur->size - len < sizeof(memory_header) +
256 MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
Paul Bakker6e339b52013-07-03 13:37:05 +0200257 cur->alloc = 1;
258
Paul Bakker1ef120f2013-07-03 17:20:39 +0200259 // Remove from free_list
260 //
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 if (cur->prev_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200262 cur->prev_free->next_free = cur->next_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 } else {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200264 heap.first_free = cur->next_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200266
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 if (cur->next_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200268 cur->next_free->prev_free = cur->prev_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200270
271 cur->prev_free = NULL;
272 cur->next_free = NULL;
273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200275 heap.total_used += cur->size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 if (heap.total_used > heap.maximum_used) {
Paul Bakker891998e2013-07-03 14:45:05 +0200277 heap.maximum_used = heap.total_used;
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 }
Paul Bakker891998e2013-07-03 14:45:05 +0200279#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280#if defined(MBEDTLS_MEMORY_BACKTRACE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 trace_cnt = backtrace(trace_buffer, MAX_BT);
282 cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
Paul Bakker6e339b52013-07-03 13:37:05 +0200283 cur->trace_count = trace_cnt;
284#endif
285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
287 mbedtls_exit(1);
288 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200289
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 ret = (unsigned char *) cur + sizeof(memory_header);
291 memset(ret, 0, original_len);
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 return ret;
Paul Bakker6e339b52013-07-03 13:37:05 +0200294 }
295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 p = ((unsigned char *) cur) + sizeof(memory_header) + len;
Paul Bakker6e339b52013-07-03 13:37:05 +0200297 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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200304 new->trace = NULL;
305 new->trace_count = 0;
306#endif
307 new->magic1 = MAGIC1;
308 new->magic2 = MAGIC2;
309
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if (new->next != NULL) {
Paul Bakker6e339b52013-07-03 13:37:05 +0200311 new->next->prev = new;
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200313
Paul Bakker1ef120f2013-07-03 17:20:39 +0200314 // Replace cur with new in free_list
315 //
316 new->prev_free = cur->prev_free;
317 new->next_free = cur->next_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100318 if (new->prev_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200319 new->prev_free->next_free = new;
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 } else {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200321 heap.first_free = new;
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200323
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 if (new->next_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200325 new->next_free->prev_free = new;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200327
Paul Bakker6e339b52013-07-03 13:37:05 +0200328 cur->alloc = 1;
329 cur->size = len;
330 cur->next = new;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200331 cur->prev_free = NULL;
332 cur->next_free = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200335 heap.header_count++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 if (heap.header_count > heap.maximum_header_count) {
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +0100337 heap.maximum_header_count = heap.header_count;
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 }
Paul Bakker891998e2013-07-03 14:45:05 +0200339 heap.total_used += cur->size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 if (heap.total_used > heap.maximum_used) {
Paul Bakker891998e2013-07-03 14:45:05 +0200341 heap.maximum_used = heap.total_used;
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 }
Paul Bakker891998e2013-07-03 14:45:05 +0200343#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344#if defined(MBEDTLS_MEMORY_BACKTRACE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 trace_cnt = backtrace(trace_buffer, MAX_BT);
346 cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
Paul Bakker6e339b52013-07-03 13:37:05 +0200347 cur->trace_count = trace_cnt;
348#endif
349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
351 mbedtls_exit(1);
352 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200353
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 ret = (unsigned char *) cur + sizeof(memory_header);
355 memset(ret, 0, original_len);
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200356
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 return ret;
Paul Bakker6e339b52013-07-03 13:37:05 +0200358}
359
Gilles Peskine449bd832023-01-11 14:50:10 +0100360static void buffer_alloc_free(void *ptr)
Paul Bakker6e339b52013-07-03 13:37:05 +0200361{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200362 memory_header *hdr, *old = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200363 unsigned char *p = (unsigned char *) ptr;
364
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 if (ptr == NULL || heap.buf == NULL || heap.first == NULL) {
Paul Bakker6e339b52013-07-03 13:37:05 +0200366 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200368
Gilles Peskine449bd832023-01-11 14:50:10 +0100369 if (p < heap.buf || p >= heap.buf + heap.len) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 mbedtls_fprintf(stderr, "FATAL: mbedtls_free() outside of managed "
372 "space\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200373#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 mbedtls_exit(1);
Paul Bakker6e339b52013-07-03 13:37:05 +0200375 }
376
377 p -= sizeof(memory_header);
378 hdr = (memory_header *) p;
379
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 if (verify_header(hdr) != 0) {
381 mbedtls_exit(1);
382 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200383
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if (hdr->alloc != 1) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 mbedtls_fprintf(stderr, "FATAL: mbedtls_free() on unallocated "
387 "data\n");
Paul Bakker6e339b52013-07-03 13:37:05 +0200388#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 mbedtls_exit(1);
Paul Bakker6e339b52013-07-03 13:37:05 +0200390 }
391
392 hdr->alloc = 0;
393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200395 heap.free_count++;
396 heap.total_used -= hdr->size;
397#endif
398
SimonB42256112016-05-02 01:05:22 +0100399#if defined(MBEDTLS_MEMORY_BACKTRACE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 free(hdr->trace);
SimonB42256112016-05-02 01:05:22 +0100401 hdr->trace = NULL;
402 hdr->trace_count = 0;
403#endif
404
Paul Bakker6e339b52013-07-03 13:37:05 +0200405 // Regroup with block before
406 //
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 if (hdr->prev != NULL && hdr->prev->alloc == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200409 heap.header_count--;
410#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200411 hdr->prev->size += sizeof(memory_header) + hdr->size;
412 hdr->prev->next = hdr->next;
413 old = hdr;
414 hdr = hdr->prev;
415
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 if (hdr->next != NULL) {
Paul Bakker6e339b52013-07-03 13:37:05 +0200417 hdr->next->prev = hdr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200419
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 memset(old, 0, sizeof(memory_header));
Paul Bakker6e339b52013-07-03 13:37:05 +0200421 }
422
423 // Regroup with block after
424 //
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 if (hdr->next != NULL && hdr->next->alloc == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200427 heap.header_count--;
428#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200429 hdr->size += sizeof(memory_header) + hdr->next->size;
430 old = hdr->next;
431 hdr->next = hdr->next->next;
432
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 if (hdr->prev_free != NULL || hdr->next_free != NULL) {
434 if (hdr->prev_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200435 hdr->prev_free->next_free = hdr->next_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 } else {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200437 heap.first_free = hdr->next_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 if (hdr->next_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200441 hdr->next_free->prev_free = hdr->prev_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200443 }
444
445 hdr->prev_free = old->prev_free;
446 hdr->next_free = old->next_free;
447
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if (hdr->prev_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200449 hdr->prev_free->next_free = hdr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 } else {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200451 heap.first_free = hdr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 if (hdr->next_free != NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200455 hdr->next_free->prev_free = hdr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200457
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 if (hdr->next != NULL) {
Paul Bakker6e339b52013-07-03 13:37:05 +0200459 hdr->next->prev = hdr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200461
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 memset(old, 0, sizeof(memory_header));
Paul Bakker6e339b52013-07-03 13:37:05 +0200463 }
464
Paul Bakker1ef120f2013-07-03 17:20:39 +0200465 // Prepend to free_list if we have not merged
466 // (Does not have to stay in same order as prev / next list)
467 //
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 if (old == NULL) {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200469 hdr->next_free = heap.first_free;
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 if (heap.first_free != NULL) {
Manuel Pégourié-Gonnard547ff662014-11-26 15:42:16 +0100471 heap.first_free->prev_free = hdr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200473 heap.first_free = hdr;
474 }
475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) {
477 mbedtls_exit(1);
478 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200479}
480
Gilles Peskine449bd832023-01-11 14:50:10 +0100481void mbedtls_memory_buffer_set_verify(int verify)
Paul Bakkerbf796ac2013-09-28 11:06:38 +0200482{
483 heap.verify = verify;
484}
485
Gilles Peskine449bd832023-01-11 14:50:10 +0100486int mbedtls_memory_buffer_alloc_verify(void)
Paul Bakker6e339b52013-07-03 13:37:05 +0200487{
488 return verify_chain();
489}
490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491#if defined(MBEDTLS_MEMORY_DEBUG)
Gilles Peskine449bd832023-01-11 14:50:10 +0100492void mbedtls_memory_buffer_alloc_status(void)
Paul Bakker6e339b52013-07-03 13:37:05 +0200493{
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 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);
Paul Bakker891998e2013-07-03 14:45:05 +0200502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 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");
Paul Bakker6e339b52013-07-03 13:37:05 +0200507 debug_chain();
508 }
509}
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100510
Gilles Peskine449bd832023-01-11 14:50:10 +0100511void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count)
Manuel Pégourié-Gonnard35415a02022-01-04 10:23:34 +0100512{
513 *alloc_count = heap.alloc_count;
514 *free_count = heap.free_count;
515}
516
Gilles Peskine449bd832023-01-11 14:50:10 +0100517void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks)
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100518{
519 *max_used = heap.maximum_used;
520 *max_blocks = heap.maximum_header_count;
521}
522
Gilles Peskine449bd832023-01-11 14:50:10 +0100523void mbedtls_memory_buffer_alloc_max_reset(void)
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100524{
525 heap.maximum_used = 0;
526 heap.maximum_header_count = 0;
527}
528
Gilles Peskine449bd832023-01-11 14:50:10 +0100529void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks)
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100530{
531 *cur_used = heap.total_used;
532 *cur_blocks = heap.header_count;
533}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#endif /* MBEDTLS_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100537static void *buffer_alloc_calloc_mutexed(size_t n, size_t size)
Paul Bakker1337aff2013-09-29 14:45:34 +0200538{
539 void *buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 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;
Paul Bakker1337aff2013-09-29 14:45:34 +0200548}
549
Gilles Peskine449bd832023-01-11 14:50:10 +0100550static void buffer_alloc_free_mutexed(void *ptr)
Paul Bakker1337aff2013-09-29 14:45:34 +0200551{
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800552 /* We have no good option here, but corrupting the heap seems
553 * worse than losing memory. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 if (mbedtls_mutex_lock(&heap.mutex)) {
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200555 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 }
557 buffer_alloc_free(ptr);
558 (void) mbedtls_mutex_unlock(&heap.mutex);
Paul Bakker1337aff2013-09-29 14:45:34 +0200559}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560#endif /* MBEDTLS_THREADING_C */
Paul Bakker1337aff2013-09-29 14:45:34 +0200561
Gilles Peskine449bd832023-01-11 14:50:10 +0100562void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len)
Paul Bakker6e339b52013-07-03 13:37:05 +0200563{
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 memset(&heap, 0, sizeof(buffer_alloc_ctx));
Paul Bakker6e339b52013-07-03 13:37:05 +0200565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100567 mbedtls_mutex_init(&heap.mutex);
568 mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed,
569 buffer_alloc_free_mutexed);
Paul Bakker1337aff2013-09-29 14:45:34 +0200570#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free);
Paul Bakker1337aff2013-09-29 14:45:34 +0200572#endif
573
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
Andres AG9cf1f962017-01-30 14:34:25 +0000575 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 } else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100577 /* Adjust len first since buf is used in the computation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
Gilles Peskine449bd832023-01-11 14:50:10 +0100579 - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
Gilles Peskine449bd832023-01-11 14:50:10 +0100581 - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200582 }
583
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 memset(buf, 0, len);
Andres AG9cf1f962017-01-30 14:34:25 +0000585
Paul Bakker6e339b52013-07-03 13:37:05 +0200586 heap.buf = buf;
587 heap.len = len;
588
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 heap.first = (memory_header *) buf;
590 heap.first->size = len - sizeof(memory_header);
Paul Bakker6e339b52013-07-03 13:37:05 +0200591 heap.first->magic1 = MAGIC1;
592 heap.first->magic2 = MAGIC2;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200593 heap.first_free = heap.first;
Paul Bakker6e339b52013-07-03 13:37:05 +0200594}
595
Gilles Peskine449bd832023-01-11 14:50:10 +0100596void mbedtls_memory_buffer_alloc_free(void)
Paul Bakker1337aff2013-09-29 14:45:34 +0200597{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100599 mbedtls_mutex_free(&heap.mutex);
Paul Bakker1337aff2013-09-29 14:45:34 +0200600#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx));
Paul Bakker1337aff2013-09-29 14:45:34 +0200602}
603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604#if defined(MBEDTLS_SELF_TEST)
Gilles Peskine449bd832023-01-11 14:50:10 +0100605static int check_pointer(void *p)
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100606{
Gilles Peskine449bd832023-01-11 14:50:10 +0100607 if (p == NULL) {
608 return -1;
609 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100610
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) {
612 return -1;
613 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 return 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100616}
617
Gilles Peskine449bd832023-01-11 14:50:10 +0100618static int check_all_free(void)
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100619{
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 if (
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard491a3fe2015-02-05 12:08:47 +0100622 heap.total_used != 0 ||
623#endif
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100624 heap.first != heap.first_free ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100625 (void *) heap.first != (void *) heap.buf) {
626 return -1;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100627 }
628
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 return 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100630}
631
Gilles Peskine449bd832023-01-11 14:50:10 +0100632#define TEST_ASSERT(condition) \
633 if (!(condition)) \
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100634 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 if (verbose != 0) \
636 mbedtls_printf("failed\n"); \
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100637 \
638 ret = 1; \
639 goto cleanup; \
640 }
641
Gilles Peskine449bd832023-01-11 14:50:10 +0100642int mbedtls_memory_buffer_alloc_self_test(int verbose)
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100643{
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100644 unsigned char buf[1024];
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100645 unsigned char *p, *q, *r, *end;
646 int ret = 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100647
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 if (verbose != 0) {
649 mbedtls_printf(" MBA test #1 (basic alloc-free cycle): ");
650 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100651
Gilles Peskine449bd832023-01-11 14:50:10 +0100652 mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100653
Gilles Peskine449bd832023-01-11 14:50:10 +0100654 p = mbedtls_calloc(1, 1);
655 q = mbedtls_calloc(1, 128);
656 r = mbedtls_calloc(1, 16);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100657
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 TEST_ASSERT(check_pointer(p) == 0 &&
659 check_pointer(q) == 0 &&
660 check_pointer(r) == 0);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100661
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 mbedtls_free(r);
663 mbedtls_free(q);
664 mbedtls_free(p);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100665
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 TEST_ASSERT(check_all_free() == 0);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100667
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100668 /* Memorize end to compare with the next test */
669 end = heap.buf + heap.len;
670
Gilles Peskine449bd832023-01-11 14:50:10 +0100671 mbedtls_memory_buffer_alloc_free();
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100672
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 if (verbose != 0) {
674 mbedtls_printf("passed\n");
675 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100676
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 if (verbose != 0) {
678 mbedtls_printf(" MBA test #2 (buf not aligned): ");
679 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100680
Gilles Peskine449bd832023-01-11 14:50:10 +0100681 mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100682
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 TEST_ASSERT(heap.buf + heap.len == end);
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100684
Gilles Peskine449bd832023-01-11 14:50:10 +0100685 p = mbedtls_calloc(1, 1);
686 q = mbedtls_calloc(1, 128);
687 r = mbedtls_calloc(1, 16);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100688
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 TEST_ASSERT(check_pointer(p) == 0 &&
690 check_pointer(q) == 0 &&
691 check_pointer(r) == 0);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100692
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 mbedtls_free(r);
694 mbedtls_free(q);
695 mbedtls_free(p);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 TEST_ASSERT(check_all_free() == 0);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100698
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 mbedtls_memory_buffer_alloc_free();
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100700
Gilles Peskine449bd832023-01-11 14:50:10 +0100701 if (verbose != 0) {
702 mbedtls_printf("passed\n");
703 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100704
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 if (verbose != 0) {
706 mbedtls_printf(" MBA test #3 (full): ");
707 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100708
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100710
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header));
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100712
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 TEST_ASSERT(check_pointer(p) == 0);
714 TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100715
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 mbedtls_free(p);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100717
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16);
719 q = mbedtls_calloc(1, 16);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100720
Gilles Peskine449bd832023-01-11 14:50:10 +0100721 TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0);
722 TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100723
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 mbedtls_free(q);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100725
Gilles Peskine449bd832023-01-11 14:50:10 +0100726 TEST_ASSERT(mbedtls_calloc(1, 17) == NULL);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100727
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 mbedtls_free(p);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100729
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 TEST_ASSERT(check_all_free() == 0);
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100731
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 mbedtls_memory_buffer_alloc_free();
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100733
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 if (verbose != 0) {
735 mbedtls_printf("passed\n");
736 }
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100737
738cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 mbedtls_memory_buffer_alloc_free();
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100740
Gilles Peskine449bd832023-01-11 14:50:10 +0100741 return ret;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100742}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */