blob: 056a6ea63d96ad096e5636d25cfd613e416607af [file] [log] [blame]
Paul Bakker6e339b52013-07-03 13:37:05 +02001/*
2 * Buffer-based memory allocator
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Bence Szépkúti4e9f7122020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakker6e339b52013-07-03 13:37:05 +020024 *
Bence Szépkúti4e9f7122020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker6e339b52013-07-03 13:37:05 +020047 */
48
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020051#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020053#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000056#include "mbedtls/memory_buffer_alloc.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
59 is dependent upon MBEDTLS_PLATFORM_C */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000060#include "mbedtls/platform.h"
Rich Evansd08a6052015-02-12 12:17:10 +000061
Paul Bakker6e339b52013-07-03 13:37:05 +020062#include <string.h>
63
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020064#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020065#include <execinfo.h>
66#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000069#include "mbedtls/threading.h"
Paul Bakker1337aff2013-09-29 14:45:34 +020070#endif
71
Paul Bakker34617722014-06-13 17:20:13 +020072/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020074 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
75}
76
Paul Bakker6e339b52013-07-03 13:37:05 +020077#define MAGIC1 0xFF00AA55
78#define MAGIC2 0xEE119966
79#define MAX_BT 20
80
81typedef struct _memory_header memory_header;
82struct _memory_header
83{
84 size_t magic1;
85 size_t size;
86 size_t alloc;
87 memory_header *prev;
88 memory_header *next;
Paul Bakker1ef120f2013-07-03 17:20:39 +020089 memory_header *prev_free;
90 memory_header *next_free;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020091#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020092 char **trace;
93 size_t trace_count;
94#endif
95 size_t magic2;
96};
97
98typedef struct
99{
100 unsigned char *buf;
101 size_t len;
102 memory_header *first;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200103 memory_header *first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200104 int verify;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200106 size_t alloc_count;
Paul Bakker891998e2013-07-03 14:45:05 +0200107 size_t free_count;
108 size_t total_used;
109 size_t maximum_used;
110 size_t header_count;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +0100111 size_t maximum_header_count;
Paul Bakker891998e2013-07-03 14:45:05 +0200112#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113#if defined(MBEDTLS_THREADING_C)
114 mbedtls_threading_mutex_t mutex;
Paul Bakker1337aff2013-09-29 14:45:34 +0200115#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200116}
117buffer_alloc_ctx;
118
119static buffer_alloc_ctx heap;
120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker6e339b52013-07-03 13:37:05 +0200122static void debug_header( memory_header *hdr )
123{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200125 size_t i;
126#endif
127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200129 "ALLOC(%zu), SIZE(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100130 (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
131 hdr->alloc, hdr->size );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100133 (size_t) hdr->prev_free, (size_t) hdr->next_free );
Paul Bakker6e339b52013-07-03 13:37:05 +0200134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135#if defined(MBEDTLS_MEMORY_BACKTRACE)
136 mbedtls_fprintf( stderr, "TRACE: \n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200137 for( i = 0; i < hdr->trace_count; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] );
139 mbedtls_fprintf( stderr, "\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200140#endif
141}
142
143static void debug_chain()
144{
145 memory_header *cur = heap.first;
146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 mbedtls_fprintf( stderr, "\nBlock list\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200148 while( cur != NULL )
149 {
150 debug_header( cur );
Paul Bakker6e339b52013-07-03 13:37:05 +0200151 cur = cur->next;
152 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 mbedtls_fprintf( stderr, "Free list\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200155 cur = heap.first_free;
156
157 while( cur != NULL )
158 {
159 debug_header( cur );
160 cur = cur->next_free;
161 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200162}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163#endif /* MBEDTLS_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200164
165static int verify_header( memory_header *hdr )
166{
167 if( hdr->magic1 != MAGIC1 )
168 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169#if defined(MBEDTLS_MEMORY_DEBUG)
170 mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200171#endif
172 return( 1 );
173 }
174
175 if( hdr->magic2 != MAGIC2 )
176 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177#if defined(MBEDTLS_MEMORY_DEBUG)
178 mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200179#endif
180 return( 1 );
181 }
182
183 if( hdr->alloc > 1 )
184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185#if defined(MBEDTLS_MEMORY_DEBUG)
186 mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200187#endif
188 return( 1 );
189 }
190
Paul Bakker1ef120f2013-07-03 17:20:39 +0200191 if( hdr->prev != NULL && hdr->prev == hdr->next )
192 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193#if defined(MBEDTLS_MEMORY_DEBUG)
194 mbedtls_fprintf( stderr, "FATAL: prev == next\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200195#endif
196 return( 1 );
197 }
198
199 if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201#if defined(MBEDTLS_MEMORY_DEBUG)
202 mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200203#endif
204 return( 1 );
205 }
206
Paul Bakker6e339b52013-07-03 13:37:05 +0200207 return( 0 );
208}
209
210static int verify_chain()
211{
Andres AG9cf1f962017-01-30 14:34:25 +0000212 memory_header *prv = heap.first, *cur;
Paul Bakker6e339b52013-07-03 13:37:05 +0200213
Andres Amaya Garciaf1ee6352017-07-06 10:06:58 +0100214 if( prv == NULL || verify_header( prv ) != 0 )
Paul Bakker6e339b52013-07-03 13:37:05 +0200215 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216#if defined(MBEDTLS_MEMORY_DEBUG)
217 mbedtls_fprintf( stderr, "FATAL: verification of first header "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100218 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200219#endif
220 return( 1 );
221 }
222
223 if( heap.first->prev != NULL )
224 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225#if defined(MBEDTLS_MEMORY_DEBUG)
226 mbedtls_fprintf( stderr, "FATAL: verification failed: "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100227 "first->prev != NULL\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200228#endif
229 return( 1 );
230 }
231
Andres AG9cf1f962017-01-30 14:34:25 +0000232 cur = heap.first->next;
233
Paul Bakker6e339b52013-07-03 13:37:05 +0200234 while( cur != NULL )
235 {
236 if( verify_header( cur ) != 0 )
237 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238#if defined(MBEDTLS_MEMORY_DEBUG)
239 mbedtls_fprintf( stderr, "FATAL: verification of header "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100240 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200241#endif
242 return( 1 );
243 }
244
245 if( cur->prev != prv )
246 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247#if defined(MBEDTLS_MEMORY_DEBUG)
248 mbedtls_fprintf( stderr, "FATAL: verification failed: "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100249 "cur->prev != prv\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200250#endif
251 return( 1 );
252 }
253
254 prv = cur;
255 cur = cur->next;
256 }
257
258 return( 0 );
259}
260
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200261static void *buffer_alloc_calloc( size_t n, size_t size )
Paul Bakker6e339b52013-07-03 13:37:05 +0200262{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200263 memory_header *new, *cur = heap.first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200264 unsigned char *p;
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200265 void *ret;
266 size_t original_len, len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200268 void *trace_buffer[MAX_BT];
269 size_t trace_cnt;
270#endif
271
272 if( heap.buf == NULL || heap.first == NULL )
273 return( NULL );
274
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200275 original_len = len = n * size;
276
Andres AG9cf1f962017-01-30 14:34:25 +0000277 if( n == 0 || size == 0 || len / n != size )
278 return( NULL );
279 else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200280 return( NULL );
281
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Paul Bakker6e339b52013-07-03 13:37:05 +0200283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
285 len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Paul Bakker6e339b52013-07-03 13:37:05 +0200286 }
287
288 // Find block that fits
289 //
290 while( cur != NULL )
291 {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200292 if( cur->size >= len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200293 break;
294
Paul Bakker1ef120f2013-07-03 17:20:39 +0200295 cur = cur->next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200296 }
297
298 if( cur == NULL )
299 return( NULL );
300
Paul Bakker1ef120f2013-07-03 17:20:39 +0200301 if( cur->alloc != 0 )
302 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303#if defined(MBEDTLS_MEMORY_DEBUG)
304 mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100305 "data\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200306#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 mbedtls_exit( 1 );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200308 }
309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard6c967b92015-05-27 20:18:39 +0200311 heap.alloc_count++;
Paul Bakker891998e2013-07-03 14:45:05 +0200312#endif
313
Paul Bakker6e339b52013-07-03 13:37:05 +0200314 // Found location, split block if > memory_header + 4 room left
315 //
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200316 if( cur->size - len < sizeof(memory_header) +
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Paul Bakker6e339b52013-07-03 13:37:05 +0200318 {
319 cur->alloc = 1;
320
Paul Bakker1ef120f2013-07-03 17:20:39 +0200321 // Remove from free_list
322 //
323 if( cur->prev_free != NULL )
324 cur->prev_free->next_free = cur->next_free;
325 else
326 heap.first_free = cur->next_free;
327
328 if( cur->next_free != NULL )
329 cur->next_free->prev_free = cur->prev_free;
330
331 cur->prev_free = NULL;
332 cur->next_free = NULL;
333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200335 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200336 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200337 heap.maximum_used = heap.total_used;
338#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200340 trace_cnt = backtrace( trace_buffer, MAX_BT );
341 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
342 cur->trace_count = trace_cnt;
343#endif
344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
346 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200347
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200348 ret = (unsigned char *) cur + sizeof( memory_header );
349 memset( ret, 0, original_len );
350
351 return( ret );
Paul Bakker6e339b52013-07-03 13:37:05 +0200352 }
353
354 p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
355 new = (memory_header *) p;
356
357 new->size = cur->size - len - sizeof(memory_header);
358 new->alloc = 0;
359 new->prev = cur;
360 new->next = cur->next;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200362 new->trace = NULL;
363 new->trace_count = 0;
364#endif
365 new->magic1 = MAGIC1;
366 new->magic2 = MAGIC2;
367
368 if( new->next != NULL )
369 new->next->prev = new;
370
Paul Bakker1ef120f2013-07-03 17:20:39 +0200371 // Replace cur with new in free_list
372 //
373 new->prev_free = cur->prev_free;
374 new->next_free = cur->next_free;
375 if( new->prev_free != NULL )
376 new->prev_free->next_free = new;
377 else
378 heap.first_free = new;
379
380 if( new->next_free != NULL )
381 new->next_free->prev_free = new;
382
Paul Bakker6e339b52013-07-03 13:37:05 +0200383 cur->alloc = 1;
384 cur->size = len;
385 cur->next = new;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200386 cur->prev_free = NULL;
387 cur->next_free = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200390 heap.header_count++;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +0100391 if( heap.header_count > heap.maximum_header_count )
392 heap.maximum_header_count = heap.header_count;
Paul Bakker891998e2013-07-03 14:45:05 +0200393 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200394 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200395 heap.maximum_used = heap.total_used;
396#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200398 trace_cnt = backtrace( trace_buffer, MAX_BT );
399 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
400 cur->trace_count = trace_cnt;
401#endif
402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
404 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200405
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200406 ret = (unsigned char *) cur + sizeof( memory_header );
407 memset( ret, 0, original_len );
408
409 return( ret );
Paul Bakker6e339b52013-07-03 13:37:05 +0200410}
411
412static void buffer_alloc_free( void *ptr )
413{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200414 memory_header *hdr, *old = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200415 unsigned char *p = (unsigned char *) ptr;
416
Paul Bakker6e339b52013-07-03 13:37:05 +0200417 if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
418 return;
419
Andres AG9cf1f962017-01-30 14:34:25 +0000420 if( p < heap.buf || p >= heap.buf + heap.len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422#if defined(MBEDTLS_MEMORY_DEBUG)
423 mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100424 "space\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200425#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200427 }
428
429 p -= sizeof(memory_header);
430 hdr = (memory_header *) p;
431
432 if( verify_header( hdr ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200434
435 if( hdr->alloc != 1 )
436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437#if defined(MBEDTLS_MEMORY_DEBUG)
438 mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100439 "data\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200440#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200442 }
443
444 hdr->alloc = 0;
445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200447 heap.free_count++;
448 heap.total_used -= hdr->size;
449#endif
450
SimonB42256112016-05-02 01:05:22 +0100451#if defined(MBEDTLS_MEMORY_BACKTRACE)
452 free( hdr->trace );
453 hdr->trace = NULL;
454 hdr->trace_count = 0;
455#endif
456
Paul Bakker6e339b52013-07-03 13:37:05 +0200457 // Regroup with block before
458 //
459 if( hdr->prev != NULL && hdr->prev->alloc == 0 )
460 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200462 heap.header_count--;
463#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200464 hdr->prev->size += sizeof(memory_header) + hdr->size;
465 hdr->prev->next = hdr->next;
466 old = hdr;
467 hdr = hdr->prev;
468
469 if( hdr->next != NULL )
470 hdr->next->prev = hdr;
471
Paul Bakker6e339b52013-07-03 13:37:05 +0200472 memset( old, 0, sizeof(memory_header) );
473 }
474
475 // Regroup with block after
476 //
477 if( hdr->next != NULL && hdr->next->alloc == 0 )
478 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200480 heap.header_count--;
481#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200482 hdr->size += sizeof(memory_header) + hdr->next->size;
483 old = hdr->next;
484 hdr->next = hdr->next->next;
485
Paul Bakker1ef120f2013-07-03 17:20:39 +0200486 if( hdr->prev_free != NULL || hdr->next_free != NULL )
487 {
488 if( hdr->prev_free != NULL )
489 hdr->prev_free->next_free = hdr->next_free;
490 else
491 heap.first_free = hdr->next_free;
492
493 if( hdr->next_free != NULL )
494 hdr->next_free->prev_free = hdr->prev_free;
495 }
496
497 hdr->prev_free = old->prev_free;
498 hdr->next_free = old->next_free;
499
500 if( hdr->prev_free != NULL )
501 hdr->prev_free->next_free = hdr;
502 else
503 heap.first_free = hdr;
504
505 if( hdr->next_free != NULL )
506 hdr->next_free->prev_free = hdr;
507
Paul Bakker6e339b52013-07-03 13:37:05 +0200508 if( hdr->next != NULL )
509 hdr->next->prev = hdr;
510
Paul Bakker6e339b52013-07-03 13:37:05 +0200511 memset( old, 0, sizeof(memory_header) );
512 }
513
Paul Bakker1ef120f2013-07-03 17:20:39 +0200514 // Prepend to free_list if we have not merged
515 // (Does not have to stay in same order as prev / next list)
516 //
517 if( old == NULL )
518 {
519 hdr->next_free = heap.first_free;
Manuel Pégourié-Gonnard547ff662014-11-26 15:42:16 +0100520 if( heap.first_free != NULL )
521 heap.first_free->prev_free = hdr;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200522 heap.first_free = hdr;
523 }
524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
526 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200527}
528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529void mbedtls_memory_buffer_set_verify( int verify )
Paul Bakkerbf796ac2013-09-28 11:06:38 +0200530{
531 heap.verify = verify;
532}
533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534int mbedtls_memory_buffer_alloc_verify()
Paul Bakker6e339b52013-07-03 13:37:05 +0200535{
536 return verify_chain();
537}
538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539#if defined(MBEDTLS_MEMORY_DEBUG)
540void mbedtls_memory_buffer_alloc_status()
Paul Bakker6e339b52013-07-03 13:37:05 +0200541{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_fprintf( stderr,
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200543 "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200544 "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100545 heap.header_count, heap.total_used,
546 heap.maximum_header_count, heap.maximum_used,
547 heap.maximum_header_count * sizeof( memory_header )
548 + heap.maximum_used,
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200549 heap.alloc_count, heap.free_count );
Paul Bakker891998e2013-07-03 14:45:05 +0200550
Paul Bakker6e339b52013-07-03 13:37:05 +0200551 if( heap.first->next == NULL )
Darryl Green68207f82017-11-27 17:12:14 +0000552 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
Darryl Green68207f82017-11-27 17:12:14 +0000554 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200555 else
556 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200558 debug_chain();
559 }
560}
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100563{
564 *max_used = heap.maximum_used;
565 *max_blocks = heap.maximum_header_count;
566}
567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568void mbedtls_memory_buffer_alloc_max_reset( void )
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100569{
570 heap.maximum_used = 0;
571 heap.maximum_header_count = 0;
572}
573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100575{
576 *cur_used = heap.total_used;
577 *cur_blocks = heap.header_count;
578}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579#endif /* MBEDTLS_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200582static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
Paul Bakker1337aff2013-09-29 14:45:34 +0200583{
584 void *buf;
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200585 if( mbedtls_mutex_lock( &heap.mutex ) != 0 )
586 return( NULL );
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200587 buf = buffer_alloc_calloc( n, size );
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200588 if( mbedtls_mutex_unlock( &heap.mutex ) )
589 return( NULL );
Paul Bakker1337aff2013-09-29 14:45:34 +0200590 return( buf );
591}
592
593static void buffer_alloc_free_mutexed( void *ptr )
594{
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200595 /* We have to good option here, but corrupting the heap seems
596 * worse than loosing memory. */
597 if( mbedtls_mutex_lock( &heap.mutex ) )
598 return;
Paul Bakker1337aff2013-09-29 14:45:34 +0200599 buffer_alloc_free( ptr );
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200600 (void) mbedtls_mutex_unlock( &heap.mutex );
Paul Bakker1337aff2013-09-29 14:45:34 +0200601}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602#endif /* MBEDTLS_THREADING_C */
Paul Bakker1337aff2013-09-29 14:45:34 +0200603
Manuel Pégourié-Gonnard69a69cc2015-04-29 01:05:19 +0200604void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200605{
Andres AG9cf1f962017-01-30 14:34:25 +0000606 memset( &heap, 0, sizeof( buffer_alloc_ctx ) );
Paul Bakker6e339b52013-07-03 13:37:05 +0200607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608#if defined(MBEDTLS_THREADING_C)
609 mbedtls_mutex_init( &heap.mutex );
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200610 mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed,
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100611 buffer_alloc_free_mutexed );
Paul Bakker1337aff2013-09-29 14:45:34 +0200612#else
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200613 mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
Paul Bakker1337aff2013-09-29 14:45:34 +0200614#endif
615
Andres AG9cf1f962017-01-30 14:34:25 +0000616 if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE )
617 return;
618 else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200619 {
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100620 /* Adjust len first since buf is used in the computation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
Andres AG9cf1f962017-01-30 14:34:25 +0000622 - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
Andres AG9cf1f962017-01-30 14:34:25 +0000624 - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200625 }
626
Andres AG9cf1f962017-01-30 14:34:25 +0000627 memset( buf, 0, len );
628
Paul Bakker6e339b52013-07-03 13:37:05 +0200629 heap.buf = buf;
630 heap.len = len;
631
Andres AG9cf1f962017-01-30 14:34:25 +0000632 heap.first = (memory_header *)buf;
633 heap.first->size = len - sizeof( memory_header );
Paul Bakker6e339b52013-07-03 13:37:05 +0200634 heap.first->magic1 = MAGIC1;
635 heap.first->magic2 = MAGIC2;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200636 heap.first_free = heap.first;
Paul Bakker6e339b52013-07-03 13:37:05 +0200637}
638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639void mbedtls_memory_buffer_alloc_free()
Paul Bakker1337aff2013-09-29 14:45:34 +0200640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641#if defined(MBEDTLS_THREADING_C)
642 mbedtls_mutex_free( &heap.mutex );
Paul Bakker1337aff2013-09-29 14:45:34 +0200643#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) );
Paul Bakker1337aff2013-09-29 14:45:34 +0200645}
646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100648static int check_pointer( void *p )
649{
650 if( p == NULL )
651 return( -1 );
652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 )
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100654 return( -1 );
655
656 return( 0 );
657}
658
659static int check_all_free( )
660{
Manuel Pégourié-Gonnard491a3fe2015-02-05 12:08:47 +0100661 if(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard491a3fe2015-02-05 12:08:47 +0100663 heap.total_used != 0 ||
664#endif
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100665 heap.first != heap.first_free ||
666 (void *) heap.first != (void *) heap.buf )
667 {
668 return( -1 );
669 }
670
671 return( 0 );
672}
673
674#define TEST_ASSERT( condition ) \
675 if( ! (condition) ) \
676 { \
677 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( "failed\n" ); \
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100679 \
680 ret = 1; \
681 goto cleanup; \
682 }
683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684int mbedtls_memory_buffer_alloc_self_test( int verbose )
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100685{
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100686 unsigned char buf[1024];
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100687 unsigned char *p, *q, *r, *end;
688 int ret = 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100689
690 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100694
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200695 p = mbedtls_calloc( 1, 1 );
696 q = mbedtls_calloc( 1, 128 );
697 r = mbedtls_calloc( 1, 16 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100698
699 TEST_ASSERT( check_pointer( p ) == 0 &&
700 check_pointer( q ) == 0 &&
701 check_pointer( r ) == 0 );
702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 mbedtls_free( r );
704 mbedtls_free( q );
705 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100706
707 TEST_ASSERT( check_all_free( ) == 0 );
708
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100709 /* Memorize end to compare with the next test */
710 end = heap.buf + heap.len;
711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100713
714 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100716
717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_printf( " MBA test #2 (buf not aligned): " );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100721
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100722 TEST_ASSERT( heap.buf + heap.len == end );
723
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200724 p = mbedtls_calloc( 1, 1 );
725 q = mbedtls_calloc( 1, 128 );
726 r = mbedtls_calloc( 1, 16 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100727
728 TEST_ASSERT( check_pointer( p ) == 0 &&
729 check_pointer( q ) == 0 &&
730 check_pointer( r ) == 0 );
731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 mbedtls_free( r );
733 mbedtls_free( q );
734 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100735
736 TEST_ASSERT( check_all_free( ) == 0 );
737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100739
740 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100742
743 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 mbedtls_printf( " MBA test #3 (full): " );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100747
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200748 p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100749
750 TEST_ASSERT( check_pointer( p ) == 0 );
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200751 TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100752
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100754
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200755 p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
756 q = mbedtls_calloc( 1, 16 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100757
758 TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200759 TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 mbedtls_free( q );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100762
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200763 TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100766
767 TEST_ASSERT( check_all_free( ) == 0 );
768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100770
771 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100773
774cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100776
777 return( ret );
778}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200779#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */