Fix corner case uses of memory_buffer_alloc.c
The corner cases fixed include:
* Allocating a buffer of size 0. With this change, the allocator now
returns a NULL pointer in this case. Note that changes in pem.c and
x509_crl.c were required to fix tests that did not work under this
assumption.
* Initialising the allocator with less memory than required for headers.
* Fix header chain checks for uninitialised allocator.
diff --git a/library/memory_buffer_alloc.c b/library/memory_buffer_alloc.c
index 545d5a2..0d3342d 100644
--- a/library/memory_buffer_alloc.c
+++ b/library/memory_buffer_alloc.c
@@ -182,9 +182,9 @@
static int verify_chain()
{
- memory_header *prv = heap.first, *cur = heap.first->next;
+ memory_header *prv = heap.first, *cur;
- if( verify_header( heap.first ) != 0 )
+ if( heap.first == NULL || verify_header( heap.first ) != 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification of first header "
@@ -202,6 +202,8 @@
return( 1 );
}
+ cur = heap.first->next;
+
while( cur != NULL )
{
if( verify_header( cur ) != 0 )
@@ -245,7 +247,9 @@
original_len = len = n * size;
- if( n != 0 && len / n != size )
+ if( n == 0 || size == 0 || len / n != size )
+ return( NULL );
+ else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE )
return( NULL );
if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
@@ -386,7 +390,7 @@
if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
return;
- if( p < heap.buf || p > heap.buf + heap.len )
+ if( p < heap.buf || p >= heap.buf + heap.len )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
@@ -570,8 +574,7 @@
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
{
- memset( &heap, 0, sizeof(buffer_alloc_ctx) );
- memset( buf, 0, len );
+ memset( &heap, 0, sizeof( buffer_alloc_ctx ) );
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &heap.mutex );
@@ -581,20 +584,24 @@
mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
#endif
- if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
+ if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE )
+ return;
+ else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
/* Adjust len first since buf is used in the computation */
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
- - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+ - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
- - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+ - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
+ memset( buf, 0, len );
+
heap.buf = buf;
heap.len = len;
- heap.first = (memory_header *) buf;
- heap.first->size = len - sizeof(memory_header);
+ heap.first = (memory_header *)buf;
+ heap.first->size = len - sizeof( memory_header );
heap.first->magic1 = MAGIC1;
heap.first->magic2 = MAGIC2;
heap.first_free = heap.first;