xref: /aosp_15_r20/external/mbedtls/library/memory_buffer_alloc.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
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