blob: 44deac00fd912a266c64bc345beea1d1bc62bbdf [file] [log] [blame]
Paul Bakker6e339b52013-07-03 13:37:05 +02001/*
2 * Buffer-based memory allocator
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker6e339b52013-07-03 13:37:05 +02005 *
Manuel Pégourié-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakker6e339b52013-07-03 13:37:05 +02007 *
Paul Bakker6e339b52013-07-03 13:37:05 +02008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020023#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker6e339b52013-07-03 13:37:05 +020024#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020025#else
26#include POLARSSL_CONFIG_FILE
27#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020028
Paul Bakkerdefc0ca2014-02-04 17:30:24 +010029#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
Paul Bakker6e339b52013-07-03 13:37:05 +020030
Paul Bakkerdefc0ca2014-02-04 17:30:24 +010031#include "polarssl/memory_buffer_alloc.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020032
33#include <string.h>
34
35#if defined(POLARSSL_MEMORY_DEBUG)
Rich Evans00ab4702015-02-06 13:43:58 +000036#if defined(POLARSSL_PLATFORM_C)
37#include "polarssl/platform.h"
38#else
Paul Bakker6e339b52013-07-03 13:37:05 +020039#include <stdio.h>
Rich Evans77d36382015-01-30 12:12:11 +000040#define polarssl_exit exit
Rich Evans00ab4702015-02-06 13:43:58 +000041#define polarssl_fprintf fprintf
42#endif /* POLARSSL_PLATFORM_C */
43#endif /* POLARSSL_MEMORY_DEBUG */
Rich Evans77d36382015-01-30 12:12:11 +000044
Paul Bakker6e339b52013-07-03 13:37:05 +020045#if defined(POLARSSL_MEMORY_BACKTRACE)
46#include <execinfo.h>
47#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020048
Paul Bakker1337aff2013-09-29 14:45:34 +020049#if defined(POLARSSL_THREADING_C)
50#include "polarssl/threading.h"
51#endif
52
Paul Bakker34617722014-06-13 17:20:13 +020053/* Implementation that should never be optimized out by the compiler */
54static void polarssl_zeroize( void *v, size_t n ) {
55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Paul Bakker6e339b52013-07-03 13:37:05 +020058#define MAGIC1 0xFF00AA55
59#define MAGIC2 0xEE119966
60#define MAX_BT 20
61
62typedef struct _memory_header memory_header;
63struct _memory_header
64{
65 size_t magic1;
66 size_t size;
67 size_t alloc;
68 memory_header *prev;
69 memory_header *next;
Paul Bakker1ef120f2013-07-03 17:20:39 +020070 memory_header *prev_free;
71 memory_header *next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +020072#if defined(POLARSSL_MEMORY_BACKTRACE)
73 char **trace;
74 size_t trace_count;
75#endif
76 size_t magic2;
77};
78
79typedef struct
80{
81 unsigned char *buf;
82 size_t len;
83 memory_header *first;
Paul Bakker1ef120f2013-07-03 17:20:39 +020084 memory_header *first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +020085 size_t current_alloc_size;
86 int verify;
Paul Bakker891998e2013-07-03 14:45:05 +020087#if defined(POLARSSL_MEMORY_DEBUG)
88 size_t malloc_count;
89 size_t free_count;
90 size_t total_used;
91 size_t maximum_used;
92 size_t header_count;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +010093 size_t maximum_header_count;
Paul Bakker891998e2013-07-03 14:45:05 +020094#endif
Paul Bakker1337aff2013-09-29 14:45:34 +020095#if defined(POLARSSL_THREADING_C)
96 threading_mutex_t mutex;
97#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020098}
99buffer_alloc_ctx;
100
101static buffer_alloc_ctx heap;
102
103#if defined(POLARSSL_MEMORY_DEBUG)
104static void debug_header( memory_header *hdr )
105{
106#if defined(POLARSSL_MEMORY_BACKTRACE)
107 size_t i;
108#endif
109
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200110 polarssl_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
111 "ALLOC(%zu), SIZE(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100112 (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
113 hdr->alloc, hdr->size );
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200114 polarssl_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100115 (size_t) hdr->prev_free, (size_t) hdr->next_free );
Paul Bakker6e339b52013-07-03 13:37:05 +0200116
117#if defined(POLARSSL_MEMORY_BACKTRACE)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100118 polarssl_fprintf( stderr, "TRACE: \n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200119 for( i = 0; i < hdr->trace_count; i++ )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100120 polarssl_fprintf( stderr, "%s\n", hdr->trace[i] );
121 polarssl_fprintf( stderr, "\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200122#endif
123}
124
125static void debug_chain()
126{
127 memory_header *cur = heap.first;
128
Paul Bakker7dc4c442014-02-01 22:50:26 +0100129 polarssl_fprintf( stderr, "\nBlock list\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200130 while( cur != NULL )
131 {
132 debug_header( cur );
Paul Bakker6e339b52013-07-03 13:37:05 +0200133 cur = cur->next;
134 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200135
Paul Bakker7dc4c442014-02-01 22:50:26 +0100136 polarssl_fprintf( stderr, "Free list\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200137 cur = heap.first_free;
138
139 while( cur != NULL )
140 {
141 debug_header( cur );
142 cur = cur->next_free;
143 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200144}
145#endif /* POLARSSL_MEMORY_DEBUG */
146
147static int verify_header( memory_header *hdr )
148{
149 if( hdr->magic1 != MAGIC1 )
150 {
151#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100152 polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200153#endif
154 return( 1 );
155 }
156
157 if( hdr->magic2 != MAGIC2 )
158 {
159#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100160 polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200161#endif
162 return( 1 );
163 }
164
165 if( hdr->alloc > 1 )
166 {
167#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100168 polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200169#endif
170 return( 1 );
171 }
172
Paul Bakker1ef120f2013-07-03 17:20:39 +0200173 if( hdr->prev != NULL && hdr->prev == hdr->next )
174 {
175#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100176 polarssl_fprintf( stderr, "FATAL: prev == next\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200177#endif
178 return( 1 );
179 }
180
181 if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
182 {
183#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100184 polarssl_fprintf( stderr, "FATAL: prev_free == next_free\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200185#endif
186 return( 1 );
187 }
188
Paul Bakker6e339b52013-07-03 13:37:05 +0200189 return( 0 );
190}
191
192static int verify_chain()
193{
194 memory_header *prv = heap.first, *cur = heap.first->next;
195
196 if( verify_header( heap.first ) != 0 )
197 {
198#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100199 polarssl_fprintf( stderr, "FATAL: verification of first header "
200 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200201#endif
202 return( 1 );
203 }
204
205 if( heap.first->prev != NULL )
206 {
207#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100208 polarssl_fprintf( stderr, "FATAL: verification failed: "
209 "first->prev != NULL\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200210#endif
211 return( 1 );
212 }
213
214 while( cur != NULL )
215 {
216 if( verify_header( cur ) != 0 )
217 {
218#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100219 polarssl_fprintf( stderr, "FATAL: verification of header "
220 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200221#endif
222 return( 1 );
223 }
224
225 if( cur->prev != prv )
226 {
227#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100228 polarssl_fprintf( stderr, "FATAL: verification failed: "
229 "cur->prev != prv\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200230#endif
231 return( 1 );
232 }
233
234 prv = cur;
235 cur = cur->next;
236 }
237
238 return( 0 );
239}
240
241static void *buffer_alloc_malloc( size_t len )
242{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200243 memory_header *new, *cur = heap.first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200244 unsigned char *p;
245#if defined(POLARSSL_MEMORY_BACKTRACE)
246 void *trace_buffer[MAX_BT];
247 size_t trace_cnt;
248#endif
249
250 if( heap.buf == NULL || heap.first == NULL )
251 return( NULL );
252
253 if( len % POLARSSL_MEMORY_ALIGN_MULTIPLE )
254 {
255 len -= len % POLARSSL_MEMORY_ALIGN_MULTIPLE;
256 len += POLARSSL_MEMORY_ALIGN_MULTIPLE;
257 }
258
259 // Find block that fits
260 //
261 while( cur != NULL )
262 {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200263 if( cur->size >= len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200264 break;
265
Paul Bakker1ef120f2013-07-03 17:20:39 +0200266 cur = cur->next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200267 }
268
269 if( cur == NULL )
270 return( NULL );
271
Paul Bakker1ef120f2013-07-03 17:20:39 +0200272 if( cur->alloc != 0 )
273 {
274#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100275 polarssl_fprintf( stderr, "FATAL: block in free_list but allocated "
276 "data\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200277#endif
Rich Evans77d36382015-01-30 12:12:11 +0000278 polarssl_exit( 1 );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200279 }
280
Paul Bakker891998e2013-07-03 14:45:05 +0200281#if defined(POLARSSL_MEMORY_DEBUG)
282 heap.malloc_count++;
283#endif
284
Paul Bakker6e339b52013-07-03 13:37:05 +0200285 // Found location, split block if > memory_header + 4 room left
286 //
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200287 if( cur->size - len < sizeof(memory_header) +
288 POLARSSL_MEMORY_ALIGN_MULTIPLE )
Paul Bakker6e339b52013-07-03 13:37:05 +0200289 {
290 cur->alloc = 1;
291
Paul Bakker1ef120f2013-07-03 17:20:39 +0200292 // Remove from free_list
293 //
294 if( cur->prev_free != NULL )
295 cur->prev_free->next_free = cur->next_free;
296 else
297 heap.first_free = cur->next_free;
298
299 if( cur->next_free != NULL )
300 cur->next_free->prev_free = cur->prev_free;
301
302 cur->prev_free = NULL;
303 cur->next_free = NULL;
304
Paul Bakker891998e2013-07-03 14:45:05 +0200305#if defined(POLARSSL_MEMORY_DEBUG)
306 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200307 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200308 heap.maximum_used = heap.total_used;
309#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200310#if defined(POLARSSL_MEMORY_BACKTRACE)
311 trace_cnt = backtrace( trace_buffer, MAX_BT );
312 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
313 cur->trace_count = trace_cnt;
314#endif
315
316 if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000317 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200318
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200319 return( ( (unsigned char *) cur ) + sizeof(memory_header) );
Paul Bakker6e339b52013-07-03 13:37:05 +0200320 }
321
322 p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
323 new = (memory_header *) p;
324
325 new->size = cur->size - len - sizeof(memory_header);
326 new->alloc = 0;
327 new->prev = cur;
328 new->next = cur->next;
329#if defined(POLARSSL_MEMORY_BACKTRACE)
330 new->trace = NULL;
331 new->trace_count = 0;
332#endif
333 new->magic1 = MAGIC1;
334 new->magic2 = MAGIC2;
335
336 if( new->next != NULL )
337 new->next->prev = new;
338
Paul Bakker1ef120f2013-07-03 17:20:39 +0200339 // Replace cur with new in free_list
340 //
341 new->prev_free = cur->prev_free;
342 new->next_free = cur->next_free;
343 if( new->prev_free != NULL )
344 new->prev_free->next_free = new;
345 else
346 heap.first_free = new;
347
348 if( new->next_free != NULL )
349 new->next_free->prev_free = new;
350
Paul Bakker6e339b52013-07-03 13:37:05 +0200351 cur->alloc = 1;
352 cur->size = len;
353 cur->next = new;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200354 cur->prev_free = NULL;
355 cur->next_free = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200356
Paul Bakker891998e2013-07-03 14:45:05 +0200357#if defined(POLARSSL_MEMORY_DEBUG)
358 heap.header_count++;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +0100359 if( heap.header_count > heap.maximum_header_count )
360 heap.maximum_header_count = heap.header_count;
Paul Bakker891998e2013-07-03 14:45:05 +0200361 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200362 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200363 heap.maximum_used = heap.total_used;
364#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200365#if defined(POLARSSL_MEMORY_BACKTRACE)
366 trace_cnt = backtrace( trace_buffer, MAX_BT );
367 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
368 cur->trace_count = trace_cnt;
369#endif
370
371 if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000372 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200373
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200374 return( ( (unsigned char *) cur ) + sizeof(memory_header) );
Paul Bakker6e339b52013-07-03 13:37:05 +0200375}
376
377static void buffer_alloc_free( void *ptr )
378{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200379 memory_header *hdr, *old = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200380 unsigned char *p = (unsigned char *) ptr;
381
Paul Bakker6e339b52013-07-03 13:37:05 +0200382 if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
383 return;
384
385 if( p < heap.buf || p > heap.buf + heap.len )
386 {
387#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100388 polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed "
389 "space\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200390#endif
Rich Evans77d36382015-01-30 12:12:11 +0000391 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200392 }
393
394 p -= sizeof(memory_header);
395 hdr = (memory_header *) p;
396
397 if( verify_header( hdr ) != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000398 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200399
400 if( hdr->alloc != 1 )
401 {
402#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100403 polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated "
404 "data\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200405#endif
Rich Evans77d36382015-01-30 12:12:11 +0000406 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200407 }
408
409 hdr->alloc = 0;
410
Paul Bakker891998e2013-07-03 14:45:05 +0200411#if defined(POLARSSL_MEMORY_DEBUG)
412 heap.free_count++;
413 heap.total_used -= hdr->size;
414#endif
415
Paul Bakker6e339b52013-07-03 13:37:05 +0200416 // Regroup with block before
417 //
418 if( hdr->prev != NULL && hdr->prev->alloc == 0 )
419 {
Paul Bakker891998e2013-07-03 14:45:05 +0200420#if defined(POLARSSL_MEMORY_DEBUG)
421 heap.header_count--;
422#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200423 hdr->prev->size += sizeof(memory_header) + hdr->size;
424 hdr->prev->next = hdr->next;
425 old = hdr;
426 hdr = hdr->prev;
427
428 if( hdr->next != NULL )
429 hdr->next->prev = hdr;
430
431#if defined(POLARSSL_MEMORY_BACKTRACE)
432 free( old->trace );
433#endif
434 memset( old, 0, sizeof(memory_header) );
435 }
436
437 // Regroup with block after
438 //
439 if( hdr->next != NULL && hdr->next->alloc == 0 )
440 {
Paul Bakker891998e2013-07-03 14:45:05 +0200441#if defined(POLARSSL_MEMORY_DEBUG)
442 heap.header_count--;
443#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200444 hdr->size += sizeof(memory_header) + hdr->next->size;
445 old = hdr->next;
446 hdr->next = hdr->next->next;
447
Paul Bakker1ef120f2013-07-03 17:20:39 +0200448 if( hdr->prev_free != NULL || hdr->next_free != NULL )
449 {
450 if( hdr->prev_free != NULL )
451 hdr->prev_free->next_free = hdr->next_free;
452 else
453 heap.first_free = hdr->next_free;
454
455 if( hdr->next_free != NULL )
456 hdr->next_free->prev_free = hdr->prev_free;
457 }
458
459 hdr->prev_free = old->prev_free;
460 hdr->next_free = old->next_free;
461
462 if( hdr->prev_free != NULL )
463 hdr->prev_free->next_free = hdr;
464 else
465 heap.first_free = hdr;
466
467 if( hdr->next_free != NULL )
468 hdr->next_free->prev_free = hdr;
469
Paul Bakker6e339b52013-07-03 13:37:05 +0200470 if( hdr->next != NULL )
471 hdr->next->prev = hdr;
472
473#if defined(POLARSSL_MEMORY_BACKTRACE)
474 free( old->trace );
475#endif
476 memset( old, 0, sizeof(memory_header) );
477 }
478
Paul Bakker1ef120f2013-07-03 17:20:39 +0200479 // Prepend to free_list if we have not merged
480 // (Does not have to stay in same order as prev / next list)
481 //
482 if( old == NULL )
483 {
484 hdr->next_free = heap.first_free;
Manuel Pégourié-Gonnard547ff662014-11-26 15:42:16 +0100485 if( heap.first_free != NULL )
486 heap.first_free->prev_free = hdr;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200487 heap.first_free = hdr;
488 }
489
Paul Bakker6e339b52013-07-03 13:37:05 +0200490#if defined(POLARSSL_MEMORY_BACKTRACE)
491 hdr->trace = NULL;
492 hdr->trace_count = 0;
493#endif
494
495 if( ( heap.verify & MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000496 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200497}
498
Paul Bakkerbf796ac2013-09-28 11:06:38 +0200499void memory_buffer_set_verify( int verify )
500{
501 heap.verify = verify;
502}
503
Paul Bakker6e339b52013-07-03 13:37:05 +0200504int memory_buffer_alloc_verify()
505{
506 return verify_chain();
507}
508
509#if defined(POLARSSL_MEMORY_DEBUG)
510void memory_buffer_alloc_status()
511{
Paul Bakker7dc4c442014-02-01 22:50:26 +0100512 polarssl_fprintf( stderr,
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200513 "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
514 "%zu bytes (total %zu bytes), malloc / free: %zu / %zu\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100515 heap.header_count, heap.total_used,
516 heap.maximum_header_count, heap.maximum_used,
517 heap.maximum_header_count * sizeof( memory_header )
518 + heap.maximum_used,
519 heap.malloc_count, heap.free_count );
Paul Bakker891998e2013-07-03 14:45:05 +0200520
Paul Bakker6e339b52013-07-03 13:37:05 +0200521 if( heap.first->next == NULL )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100522 polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200523 else
524 {
Paul Bakker7dc4c442014-02-01 22:50:26 +0100525 polarssl_fprintf( stderr, "Memory currently allocated:\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200526 debug_chain();
527 }
528}
Paul Bakker119602b2014-02-05 15:42:55 +0100529#endif /* POLARSSL_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200530
Paul Bakker1337aff2013-09-29 14:45:34 +0200531#if defined(POLARSSL_THREADING_C)
532static void *buffer_alloc_malloc_mutexed( size_t len )
533{
534 void *buf;
535 polarssl_mutex_lock( &heap.mutex );
536 buf = buffer_alloc_malloc( len );
537 polarssl_mutex_unlock( &heap.mutex );
538 return( buf );
539}
540
541static void buffer_alloc_free_mutexed( void *ptr )
542{
543 polarssl_mutex_lock( &heap.mutex );
544 buffer_alloc_free( ptr );
545 polarssl_mutex_unlock( &heap.mutex );
546}
Paul Bakker9af723c2014-05-01 13:03:14 +0200547#endif /* POLARSSL_THREADING_C */
Paul Bakker1337aff2013-09-29 14:45:34 +0200548
Paul Bakker6e339b52013-07-03 13:37:05 +0200549int memory_buffer_alloc_init( unsigned char *buf, size_t len )
550{
Paul Bakker6e339b52013-07-03 13:37:05 +0200551 memset( &heap, 0, sizeof(buffer_alloc_ctx) );
552 memset( buf, 0, len );
553
Paul Bakker1337aff2013-09-29 14:45:34 +0200554#if defined(POLARSSL_THREADING_C)
555 polarssl_mutex_init( &heap.mutex );
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100556 platform_set_malloc_free( buffer_alloc_malloc_mutexed,
557 buffer_alloc_free_mutexed );
Paul Bakker1337aff2013-09-29 14:45:34 +0200558#else
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100559 platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free );
Paul Bakker1337aff2013-09-29 14:45:34 +0200560#endif
561
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200562 if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE )
563 {
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100564 /* Adjust len first since buf is used in the computation */
565 len -= POLARSSL_MEMORY_ALIGN_MULTIPLE
566 - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200567 buf += POLARSSL_MEMORY_ALIGN_MULTIPLE
568 - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200569 }
570
Paul Bakker6e339b52013-07-03 13:37:05 +0200571 heap.buf = buf;
572 heap.len = len;
573
574 heap.first = (memory_header *) buf;
575 heap.first->size = len - sizeof(memory_header);
576 heap.first->magic1 = MAGIC1;
577 heap.first->magic2 = MAGIC2;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200578 heap.first_free = heap.first;
Paul Bakker6e339b52013-07-03 13:37:05 +0200579 return( 0 );
580}
581
Paul Bakker1337aff2013-09-29 14:45:34 +0200582void memory_buffer_alloc_free()
583{
584#if defined(POLARSSL_THREADING_C)
585 polarssl_mutex_free( &heap.mutex );
586#endif
Paul Bakker34617722014-06-13 17:20:13 +0200587 polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) );
Paul Bakker1337aff2013-09-29 14:45:34 +0200588}
589
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100590#if defined(POLARSSL_SELF_TEST)
591static int check_pointer( void *p )
592{
593 if( p == NULL )
594 return( -1 );
595
596 if( (size_t) p % POLARSSL_MEMORY_ALIGN_MULTIPLE != 0 )
597 return( -1 );
598
599 return( 0 );
600}
601
602static int check_all_free( )
603{
604 if( heap.current_alloc_size != 0 ||
605 heap.first != heap.first_free ||
606 (void *) heap.first != (void *) heap.buf )
607 {
608 return( -1 );
609 }
610
611 return( 0 );
612}
613
614#define TEST_ASSERT( condition ) \
615 if( ! (condition) ) \
616 { \
617 if( verbose != 0 ) \
618 polarssl_printf( "failed\n" ); \
619 \
620 ret = 1; \
621 goto cleanup; \
622 }
623
624int memory_buffer_alloc_self_test( int verbose )
625{
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100626 unsigned char buf[1024];
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100627 unsigned char *p, *q, *r, *end;
628 int ret = 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100629
630 if( verbose != 0 )
631 polarssl_printf( " MBA test #1 (basic alloc-free cycle): " );
632
633 memory_buffer_alloc_init( buf, sizeof( buf ) );
634
635 p = polarssl_malloc( 1 );
636 q = polarssl_malloc( 128 );
637 r = polarssl_malloc( 16 );
638
639 TEST_ASSERT( check_pointer( p ) == 0 &&
640 check_pointer( q ) == 0 &&
641 check_pointer( r ) == 0 );
642
643 polarssl_free( r );
644 polarssl_free( q );
645 polarssl_free( p );
646
647 TEST_ASSERT( check_all_free( ) == 0 );
648
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100649 /* Memorize end to compare with the next test */
650 end = heap.buf + heap.len;
651
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100652 memory_buffer_alloc_free( );
653
654 if( verbose != 0 )
655 polarssl_printf( "passed\n" );
656
657 if( verbose != 0 )
658 polarssl_printf( " MBA test #2 (buf not aligned): " );
659
660 memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
661
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100662 TEST_ASSERT( heap.buf + heap.len == end );
663
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100664 p = polarssl_malloc( 1 );
665 q = polarssl_malloc( 128 );
666 r = polarssl_malloc( 16 );
667
668 TEST_ASSERT( check_pointer( p ) == 0 &&
669 check_pointer( q ) == 0 &&
670 check_pointer( r ) == 0 );
671
672 polarssl_free( r );
673 polarssl_free( q );
674 polarssl_free( p );
675
676 TEST_ASSERT( check_all_free( ) == 0 );
677
678 memory_buffer_alloc_free( );
679
680 if( verbose != 0 )
681 polarssl_printf( "passed\n" );
682
683 if( verbose != 0 )
684 polarssl_printf( " MBA test #3 (full): " );
685
686 memory_buffer_alloc_init( buf, sizeof( buf ) );
687
688 p = polarssl_malloc( sizeof( buf ) - sizeof( memory_header ) );
689
690 TEST_ASSERT( check_pointer( p ) == 0 );
691 TEST_ASSERT( polarssl_malloc( 1 ) == NULL );
692
693 polarssl_free( p );
694
695 p = polarssl_malloc( sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
696 q = polarssl_malloc( 16 );
697
698 TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
699 TEST_ASSERT( polarssl_malloc( 1 ) == NULL );
700
701 polarssl_free( q );
702
703 TEST_ASSERT( polarssl_malloc( 17 ) == NULL );
704
705 polarssl_free( p );
706
707 TEST_ASSERT( check_all_free( ) == 0 );
708
709 memory_buffer_alloc_free( );
710
711 if( verbose != 0 )
712 polarssl_printf( "passed\n" );
713
714cleanup:
715 memory_buffer_alloc_free( );
716
717 return( ret );
718}
719#endif /* POLARSSL_SELF_TEST */
720
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100721#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */