blob: 5eb8ab138cd110ba8f774d502709be61a195003d [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é-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.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 Bakkerdefc0ca2014-02-04 17:30:24 +010030#include "polarssl/memory_buffer_alloc.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020031
Rich Evansd08a6052015-02-12 12:17:10 +000032/* No need for the header guard as POLARSSL_MEMORY_BUFFER_ALLOC_C
33 is dependent upon POLARSSL_PLATFORM_C */
34#include "polarssl/platform.h"
35
Paul Bakker6e339b52013-07-03 13:37:05 +020036#include <string.h>
37
Paul Bakker6e339b52013-07-03 13:37:05 +020038#if defined(POLARSSL_MEMORY_BACKTRACE)
39#include <execinfo.h>
40#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020041
Paul Bakker1337aff2013-09-29 14:45:34 +020042#if defined(POLARSSL_THREADING_C)
43#include "polarssl/threading.h"
44#endif
45
Paul Bakker34617722014-06-13 17:20:13 +020046/* Implementation that should never be optimized out by the compiler */
47static void polarssl_zeroize( void *v, size_t n ) {
48 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
49}
50
Paul Bakker6e339b52013-07-03 13:37:05 +020051#define MAGIC1 0xFF00AA55
52#define MAGIC2 0xEE119966
53#define MAX_BT 20
54
55typedef struct _memory_header memory_header;
56struct _memory_header
57{
58 size_t magic1;
59 size_t size;
60 size_t alloc;
61 memory_header *prev;
62 memory_header *next;
Paul Bakker1ef120f2013-07-03 17:20:39 +020063 memory_header *prev_free;
64 memory_header *next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +020065#if defined(POLARSSL_MEMORY_BACKTRACE)
66 char **trace;
67 size_t trace_count;
68#endif
69 size_t magic2;
70};
71
72typedef struct
73{
74 unsigned char *buf;
75 size_t len;
76 memory_header *first;
Paul Bakker1ef120f2013-07-03 17:20:39 +020077 memory_header *first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +020078 int verify;
Paul Bakker891998e2013-07-03 14:45:05 +020079#if defined(POLARSSL_MEMORY_DEBUG)
80 size_t malloc_count;
81 size_t free_count;
82 size_t total_used;
83 size_t maximum_used;
84 size_t header_count;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +010085 size_t maximum_header_count;
Paul Bakker891998e2013-07-03 14:45:05 +020086#endif
Paul Bakker1337aff2013-09-29 14:45:34 +020087#if defined(POLARSSL_THREADING_C)
88 threading_mutex_t mutex;
89#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020090}
91buffer_alloc_ctx;
92
93static buffer_alloc_ctx heap;
94
95#if defined(POLARSSL_MEMORY_DEBUG)
96static void debug_header( memory_header *hdr )
97{
98#if defined(POLARSSL_MEMORY_BACKTRACE)
99 size_t i;
100#endif
101
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200102 polarssl_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
103 "ALLOC(%zu), SIZE(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100104 (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
105 hdr->alloc, hdr->size );
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200106 polarssl_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100107 (size_t) hdr->prev_free, (size_t) hdr->next_free );
Paul Bakker6e339b52013-07-03 13:37:05 +0200108
109#if defined(POLARSSL_MEMORY_BACKTRACE)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100110 polarssl_fprintf( stderr, "TRACE: \n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200111 for( i = 0; i < hdr->trace_count; i++ )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100112 polarssl_fprintf( stderr, "%s\n", hdr->trace[i] );
113 polarssl_fprintf( stderr, "\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200114#endif
115}
116
117static void debug_chain()
118{
119 memory_header *cur = heap.first;
120
Paul Bakker7dc4c442014-02-01 22:50:26 +0100121 polarssl_fprintf( stderr, "\nBlock list\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200122 while( cur != NULL )
123 {
124 debug_header( cur );
Paul Bakker6e339b52013-07-03 13:37:05 +0200125 cur = cur->next;
126 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200127
Paul Bakker7dc4c442014-02-01 22:50:26 +0100128 polarssl_fprintf( stderr, "Free list\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200129 cur = heap.first_free;
130
131 while( cur != NULL )
132 {
133 debug_header( cur );
134 cur = cur->next_free;
135 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200136}
137#endif /* POLARSSL_MEMORY_DEBUG */
138
139static int verify_header( memory_header *hdr )
140{
141 if( hdr->magic1 != MAGIC1 )
142 {
143#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100144 polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200145#endif
146 return( 1 );
147 }
148
149 if( hdr->magic2 != MAGIC2 )
150 {
151#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100152 polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200153#endif
154 return( 1 );
155 }
156
157 if( hdr->alloc > 1 )
158 {
159#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100160 polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200161#endif
162 return( 1 );
163 }
164
Paul Bakker1ef120f2013-07-03 17:20:39 +0200165 if( hdr->prev != NULL && hdr->prev == hdr->next )
166 {
167#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100168 polarssl_fprintf( stderr, "FATAL: prev == next\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200169#endif
170 return( 1 );
171 }
172
173 if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
174 {
175#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100176 polarssl_fprintf( stderr, "FATAL: prev_free == next_free\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200177#endif
178 return( 1 );
179 }
180
Paul Bakker6e339b52013-07-03 13:37:05 +0200181 return( 0 );
182}
183
184static int verify_chain()
185{
186 memory_header *prv = heap.first, *cur = heap.first->next;
187
188 if( verify_header( heap.first ) != 0 )
189 {
190#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100191 polarssl_fprintf( stderr, "FATAL: verification of first header "
192 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200193#endif
194 return( 1 );
195 }
196
197 if( heap.first->prev != NULL )
198 {
199#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100200 polarssl_fprintf( stderr, "FATAL: verification failed: "
201 "first->prev != NULL\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200202#endif
203 return( 1 );
204 }
205
206 while( cur != NULL )
207 {
208 if( verify_header( cur ) != 0 )
209 {
210#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100211 polarssl_fprintf( stderr, "FATAL: verification of header "
212 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200213#endif
214 return( 1 );
215 }
216
217 if( cur->prev != prv )
218 {
219#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100220 polarssl_fprintf( stderr, "FATAL: verification failed: "
221 "cur->prev != prv\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200222#endif
223 return( 1 );
224 }
225
226 prv = cur;
227 cur = cur->next;
228 }
229
230 return( 0 );
231}
232
233static void *buffer_alloc_malloc( size_t len )
234{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200235 memory_header *new, *cur = heap.first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200236 unsigned char *p;
237#if defined(POLARSSL_MEMORY_BACKTRACE)
238 void *trace_buffer[MAX_BT];
239 size_t trace_cnt;
240#endif
241
242 if( heap.buf == NULL || heap.first == NULL )
243 return( NULL );
244
245 if( len % POLARSSL_MEMORY_ALIGN_MULTIPLE )
246 {
247 len -= len % POLARSSL_MEMORY_ALIGN_MULTIPLE;
248 len += POLARSSL_MEMORY_ALIGN_MULTIPLE;
249 }
250
251 // Find block that fits
252 //
253 while( cur != NULL )
254 {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200255 if( cur->size >= len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200256 break;
257
Paul Bakker1ef120f2013-07-03 17:20:39 +0200258 cur = cur->next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200259 }
260
261 if( cur == NULL )
262 return( NULL );
263
Paul Bakker1ef120f2013-07-03 17:20:39 +0200264 if( cur->alloc != 0 )
265 {
266#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100267 polarssl_fprintf( stderr, "FATAL: block in free_list but allocated "
268 "data\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200269#endif
Rich Evans77d36382015-01-30 12:12:11 +0000270 polarssl_exit( 1 );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200271 }
272
Paul Bakker891998e2013-07-03 14:45:05 +0200273#if defined(POLARSSL_MEMORY_DEBUG)
274 heap.malloc_count++;
275#endif
276
Paul Bakker6e339b52013-07-03 13:37:05 +0200277 // Found location, split block if > memory_header + 4 room left
278 //
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200279 if( cur->size - len < sizeof(memory_header) +
280 POLARSSL_MEMORY_ALIGN_MULTIPLE )
Paul Bakker6e339b52013-07-03 13:37:05 +0200281 {
282 cur->alloc = 1;
283
Paul Bakker1ef120f2013-07-03 17:20:39 +0200284 // Remove from free_list
285 //
286 if( cur->prev_free != NULL )
287 cur->prev_free->next_free = cur->next_free;
288 else
289 heap.first_free = cur->next_free;
290
291 if( cur->next_free != NULL )
292 cur->next_free->prev_free = cur->prev_free;
293
294 cur->prev_free = NULL;
295 cur->next_free = NULL;
296
Paul Bakker891998e2013-07-03 14:45:05 +0200297#if defined(POLARSSL_MEMORY_DEBUG)
298 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200299 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200300 heap.maximum_used = heap.total_used;
301#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200302#if defined(POLARSSL_MEMORY_BACKTRACE)
303 trace_cnt = backtrace( trace_buffer, MAX_BT );
304 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
305 cur->trace_count = trace_cnt;
306#endif
307
308 if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000309 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200310
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200311 return( ( (unsigned char *) cur ) + sizeof(memory_header) );
Paul Bakker6e339b52013-07-03 13:37:05 +0200312 }
313
314 p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
315 new = (memory_header *) p;
316
317 new->size = cur->size - len - sizeof(memory_header);
318 new->alloc = 0;
319 new->prev = cur;
320 new->next = cur->next;
321#if defined(POLARSSL_MEMORY_BACKTRACE)
322 new->trace = NULL;
323 new->trace_count = 0;
324#endif
325 new->magic1 = MAGIC1;
326 new->magic2 = MAGIC2;
327
328 if( new->next != NULL )
329 new->next->prev = new;
330
Paul Bakker1ef120f2013-07-03 17:20:39 +0200331 // Replace cur with new in free_list
332 //
333 new->prev_free = cur->prev_free;
334 new->next_free = cur->next_free;
335 if( new->prev_free != NULL )
336 new->prev_free->next_free = new;
337 else
338 heap.first_free = new;
339
340 if( new->next_free != NULL )
341 new->next_free->prev_free = new;
342
Paul Bakker6e339b52013-07-03 13:37:05 +0200343 cur->alloc = 1;
344 cur->size = len;
345 cur->next = new;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200346 cur->prev_free = NULL;
347 cur->next_free = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200348
Paul Bakker891998e2013-07-03 14:45:05 +0200349#if defined(POLARSSL_MEMORY_DEBUG)
350 heap.header_count++;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +0100351 if( heap.header_count > heap.maximum_header_count )
352 heap.maximum_header_count = heap.header_count;
Paul Bakker891998e2013-07-03 14:45:05 +0200353 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200354 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200355 heap.maximum_used = heap.total_used;
356#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200357#if defined(POLARSSL_MEMORY_BACKTRACE)
358 trace_cnt = backtrace( trace_buffer, MAX_BT );
359 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
360 cur->trace_count = trace_cnt;
361#endif
362
363 if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000364 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200365
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200366 return( ( (unsigned char *) cur ) + sizeof(memory_header) );
Paul Bakker6e339b52013-07-03 13:37:05 +0200367}
368
369static void buffer_alloc_free( void *ptr )
370{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200371 memory_header *hdr, *old = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200372 unsigned char *p = (unsigned char *) ptr;
373
Paul Bakker6e339b52013-07-03 13:37:05 +0200374 if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
375 return;
376
377 if( p < heap.buf || p > heap.buf + heap.len )
378 {
379#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100380 polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed "
381 "space\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200382#endif
Rich Evans77d36382015-01-30 12:12:11 +0000383 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200384 }
385
386 p -= sizeof(memory_header);
387 hdr = (memory_header *) p;
388
389 if( verify_header( hdr ) != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000390 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200391
392 if( hdr->alloc != 1 )
393 {
394#if defined(POLARSSL_MEMORY_DEBUG)
Paul Bakker7dc4c442014-02-01 22:50:26 +0100395 polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated "
396 "data\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200397#endif
Rich Evans77d36382015-01-30 12:12:11 +0000398 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200399 }
400
401 hdr->alloc = 0;
402
Paul Bakker891998e2013-07-03 14:45:05 +0200403#if defined(POLARSSL_MEMORY_DEBUG)
404 heap.free_count++;
405 heap.total_used -= hdr->size;
406#endif
407
Paul Bakker6e339b52013-07-03 13:37:05 +0200408 // Regroup with block before
409 //
410 if( hdr->prev != NULL && hdr->prev->alloc == 0 )
411 {
Paul Bakker891998e2013-07-03 14:45:05 +0200412#if defined(POLARSSL_MEMORY_DEBUG)
413 heap.header_count--;
414#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200415 hdr->prev->size += sizeof(memory_header) + hdr->size;
416 hdr->prev->next = hdr->next;
417 old = hdr;
418 hdr = hdr->prev;
419
420 if( hdr->next != NULL )
421 hdr->next->prev = hdr;
422
423#if defined(POLARSSL_MEMORY_BACKTRACE)
424 free( old->trace );
425#endif
426 memset( old, 0, sizeof(memory_header) );
427 }
428
429 // Regroup with block after
430 //
431 if( hdr->next != NULL && hdr->next->alloc == 0 )
432 {
Paul Bakker891998e2013-07-03 14:45:05 +0200433#if defined(POLARSSL_MEMORY_DEBUG)
434 heap.header_count--;
435#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200436 hdr->size += sizeof(memory_header) + hdr->next->size;
437 old = hdr->next;
438 hdr->next = hdr->next->next;
439
Paul Bakker1ef120f2013-07-03 17:20:39 +0200440 if( hdr->prev_free != NULL || hdr->next_free != NULL )
441 {
442 if( hdr->prev_free != NULL )
443 hdr->prev_free->next_free = hdr->next_free;
444 else
445 heap.first_free = hdr->next_free;
446
447 if( hdr->next_free != NULL )
448 hdr->next_free->prev_free = hdr->prev_free;
449 }
450
451 hdr->prev_free = old->prev_free;
452 hdr->next_free = old->next_free;
453
454 if( hdr->prev_free != NULL )
455 hdr->prev_free->next_free = hdr;
456 else
457 heap.first_free = hdr;
458
459 if( hdr->next_free != NULL )
460 hdr->next_free->prev_free = hdr;
461
Paul Bakker6e339b52013-07-03 13:37:05 +0200462 if( hdr->next != NULL )
463 hdr->next->prev = hdr;
464
465#if defined(POLARSSL_MEMORY_BACKTRACE)
466 free( old->trace );
467#endif
468 memset( old, 0, sizeof(memory_header) );
469 }
470
Paul Bakker1ef120f2013-07-03 17:20:39 +0200471 // Prepend to free_list if we have not merged
472 // (Does not have to stay in same order as prev / next list)
473 //
474 if( old == NULL )
475 {
476 hdr->next_free = heap.first_free;
Manuel Pégourié-Gonnard547ff662014-11-26 15:42:16 +0100477 if( heap.first_free != NULL )
478 heap.first_free->prev_free = hdr;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200479 heap.first_free = hdr;
480 }
481
Paul Bakker6e339b52013-07-03 13:37:05 +0200482#if defined(POLARSSL_MEMORY_BACKTRACE)
483 hdr->trace = NULL;
484 hdr->trace_count = 0;
485#endif
486
487 if( ( heap.verify & MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
Rich Evans77d36382015-01-30 12:12:11 +0000488 polarssl_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200489}
490
Paul Bakkerbf796ac2013-09-28 11:06:38 +0200491void memory_buffer_set_verify( int verify )
492{
493 heap.verify = verify;
494}
495
Paul Bakker6e339b52013-07-03 13:37:05 +0200496int memory_buffer_alloc_verify()
497{
498 return verify_chain();
499}
500
501#if defined(POLARSSL_MEMORY_DEBUG)
502void memory_buffer_alloc_status()
503{
Paul Bakker7dc4c442014-02-01 22:50:26 +0100504 polarssl_fprintf( stderr,
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200505 "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
506 "%zu bytes (total %zu bytes), malloc / free: %zu / %zu\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100507 heap.header_count, heap.total_used,
508 heap.maximum_header_count, heap.maximum_used,
509 heap.maximum_header_count * sizeof( memory_header )
510 + heap.maximum_used,
511 heap.malloc_count, heap.free_count );
Paul Bakker891998e2013-07-03 14:45:05 +0200512
Paul Bakker6e339b52013-07-03 13:37:05 +0200513 if( heap.first->next == NULL )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100514 polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200515 else
516 {
Paul Bakker7dc4c442014-02-01 22:50:26 +0100517 polarssl_fprintf( stderr, "Memory currently allocated:\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200518 debug_chain();
519 }
520}
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100521
522void memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
523{
524 *max_used = heap.maximum_used;
525 *max_blocks = heap.maximum_header_count;
526}
527
528void memory_buffer_alloc_max_reset( void )
529{
530 heap.maximum_used = 0;
531 heap.maximum_header_count = 0;
532}
533
534void memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
535{
536 *cur_used = heap.total_used;
537 *cur_blocks = heap.header_count;
538}
Paul Bakker119602b2014-02-05 15:42:55 +0100539#endif /* POLARSSL_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200540
Paul Bakker1337aff2013-09-29 14:45:34 +0200541#if defined(POLARSSL_THREADING_C)
542static void *buffer_alloc_malloc_mutexed( size_t len )
543{
544 void *buf;
545 polarssl_mutex_lock( &heap.mutex );
546 buf = buffer_alloc_malloc( len );
547 polarssl_mutex_unlock( &heap.mutex );
548 return( buf );
549}
550
551static void buffer_alloc_free_mutexed( void *ptr )
552{
553 polarssl_mutex_lock( &heap.mutex );
554 buffer_alloc_free( ptr );
555 polarssl_mutex_unlock( &heap.mutex );
556}
Paul Bakker9af723c2014-05-01 13:03:14 +0200557#endif /* POLARSSL_THREADING_C */
Paul Bakker1337aff2013-09-29 14:45:34 +0200558
Paul Bakker6e339b52013-07-03 13:37:05 +0200559int memory_buffer_alloc_init( unsigned char *buf, size_t len )
560{
Paul Bakker6e339b52013-07-03 13:37:05 +0200561 memset( &heap, 0, sizeof(buffer_alloc_ctx) );
562 memset( buf, 0, len );
563
Paul Bakker1337aff2013-09-29 14:45:34 +0200564#if defined(POLARSSL_THREADING_C)
565 polarssl_mutex_init( &heap.mutex );
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100566 platform_set_malloc_free( buffer_alloc_malloc_mutexed,
567 buffer_alloc_free_mutexed );
Paul Bakker1337aff2013-09-29 14:45:34 +0200568#else
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100569 platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free );
Paul Bakker1337aff2013-09-29 14:45:34 +0200570#endif
571
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200572 if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE )
573 {
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100574 /* Adjust len first since buf is used in the computation */
575 len -= POLARSSL_MEMORY_ALIGN_MULTIPLE
576 - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200577 buf += POLARSSL_MEMORY_ALIGN_MULTIPLE
578 - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200579 }
580
Paul Bakker6e339b52013-07-03 13:37:05 +0200581 heap.buf = buf;
582 heap.len = len;
583
584 heap.first = (memory_header *) buf;
585 heap.first->size = len - sizeof(memory_header);
586 heap.first->magic1 = MAGIC1;
587 heap.first->magic2 = MAGIC2;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200588 heap.first_free = heap.first;
Paul Bakker6e339b52013-07-03 13:37:05 +0200589 return( 0 );
590}
591
Paul Bakker1337aff2013-09-29 14:45:34 +0200592void memory_buffer_alloc_free()
593{
594#if defined(POLARSSL_THREADING_C)
595 polarssl_mutex_free( &heap.mutex );
596#endif
Paul Bakker34617722014-06-13 17:20:13 +0200597 polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) );
Paul Bakker1337aff2013-09-29 14:45:34 +0200598}
599
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100600#if defined(POLARSSL_SELF_TEST)
601static int check_pointer( void *p )
602{
603 if( p == NULL )
604 return( -1 );
605
606 if( (size_t) p % POLARSSL_MEMORY_ALIGN_MULTIPLE != 0 )
607 return( -1 );
608
609 return( 0 );
610}
611
612static int check_all_free( )
613{
Manuel Pégourié-Gonnard491a3fe2015-02-05 12:08:47 +0100614 if(
615#if defined(POLARSSL_MEMORY_DEBUG)
616 heap.total_used != 0 ||
617#endif
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100618 heap.first != heap.first_free ||
619 (void *) heap.first != (void *) heap.buf )
620 {
621 return( -1 );
622 }
623
624 return( 0 );
625}
626
627#define TEST_ASSERT( condition ) \
628 if( ! (condition) ) \
629 { \
630 if( verbose != 0 ) \
631 polarssl_printf( "failed\n" ); \
632 \
633 ret = 1; \
634 goto cleanup; \
635 }
636
637int memory_buffer_alloc_self_test( int verbose )
638{
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100639 unsigned char buf[1024];
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100640 unsigned char *p, *q, *r, *end;
641 int ret = 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100642
643 if( verbose != 0 )
644 polarssl_printf( " MBA test #1 (basic alloc-free cycle): " );
645
646 memory_buffer_alloc_init( buf, sizeof( buf ) );
647
648 p = polarssl_malloc( 1 );
649 q = polarssl_malloc( 128 );
650 r = polarssl_malloc( 16 );
651
652 TEST_ASSERT( check_pointer( p ) == 0 &&
653 check_pointer( q ) == 0 &&
654 check_pointer( r ) == 0 );
655
656 polarssl_free( r );
657 polarssl_free( q );
658 polarssl_free( p );
659
660 TEST_ASSERT( check_all_free( ) == 0 );
661
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100662 /* Memorize end to compare with the next test */
663 end = heap.buf + heap.len;
664
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100665 memory_buffer_alloc_free( );
666
667 if( verbose != 0 )
668 polarssl_printf( "passed\n" );
669
670 if( verbose != 0 )
671 polarssl_printf( " MBA test #2 (buf not aligned): " );
672
673 memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
674
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100675 TEST_ASSERT( heap.buf + heap.len == end );
676
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100677 p = polarssl_malloc( 1 );
678 q = polarssl_malloc( 128 );
679 r = polarssl_malloc( 16 );
680
681 TEST_ASSERT( check_pointer( p ) == 0 &&
682 check_pointer( q ) == 0 &&
683 check_pointer( r ) == 0 );
684
685 polarssl_free( r );
686 polarssl_free( q );
687 polarssl_free( p );
688
689 TEST_ASSERT( check_all_free( ) == 0 );
690
691 memory_buffer_alloc_free( );
692
693 if( verbose != 0 )
694 polarssl_printf( "passed\n" );
695
696 if( verbose != 0 )
697 polarssl_printf( " MBA test #3 (full): " );
698
699 memory_buffer_alloc_init( buf, sizeof( buf ) );
700
701 p = polarssl_malloc( sizeof( buf ) - sizeof( memory_header ) );
702
703 TEST_ASSERT( check_pointer( p ) == 0 );
704 TEST_ASSERT( polarssl_malloc( 1 ) == NULL );
705
706 polarssl_free( p );
707
708 p = polarssl_malloc( sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
709 q = polarssl_malloc( 16 );
710
711 TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
712 TEST_ASSERT( polarssl_malloc( 1 ) == NULL );
713
714 polarssl_free( q );
715
716 TEST_ASSERT( polarssl_malloc( 17 ) == NULL );
717
718 polarssl_free( p );
719
720 TEST_ASSERT( check_all_free( ) == 0 );
721
722 memory_buffer_alloc_free( );
723
724 if( verbose != 0 )
725 polarssl_printf( "passed\n" );
726
727cleanup:
728 memory_buffer_alloc_free( );
729
730 return( ret );
731}
732#endif /* POLARSSL_SELF_TEST */
733
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100734#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */