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