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