Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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