From bd720c316a39cba26ef7e619a70f87f9017224df Mon Sep 17 00:00:00 2001 From: Moral-Hao Date: Thu, 17 Aug 2023 00:26:58 +0800 Subject: [PATCH] Bring the heap_4 improvements to secure_heap (#749) This includes improvements like addition overflow checks, readability improvements. --- portable/ARMv8M/secure/heap/secure_heap.c | 75 +++++++++++++-------- portable/GCC/ARM_CM23/secure/secure_heap.c | 75 +++++++++++++-------- portable/GCC/ARM_CM33/secure/secure_heap.c | 75 +++++++++++++-------- portable/GCC/ARM_CM35P/secure/secure_heap.c | 75 +++++++++++++-------- portable/GCC/ARM_CM55/secure/secure_heap.c | 75 +++++++++++++-------- portable/GCC/ARM_CM85/secure/secure_heap.c | 75 +++++++++++++-------- portable/IAR/ARM_CM23/secure/secure_heap.c | 75 +++++++++++++-------- portable/IAR/ARM_CM33/secure/secure_heap.c | 75 +++++++++++++-------- portable/IAR/ARM_CM35P/secure/secure_heap.c | 75 +++++++++++++-------- portable/IAR/ARM_CM55/secure/secure_heap.c | 75 +++++++++++++-------- portable/IAR/ARM_CM85/secure/secure_heap.c | 75 +++++++++++++-------- 11 files changed, 528 insertions(+), 297 deletions(-) diff --git a/portable/ARMv8M/secure/heap/secure_heap.c b/portable/ARMv8M/secure/heap/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/ARMv8M/secure/heap/secure_heap.c +++ b/portable/ARMv8M/secure/heap/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/GCC/ARM_CM23/secure/secure_heap.c b/portable/GCC/ARM_CM23/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/GCC/ARM_CM23/secure/secure_heap.c +++ b/portable/GCC/ARM_CM23/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/GCC/ARM_CM33/secure/secure_heap.c b/portable/GCC/ARM_CM33/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/GCC/ARM_CM33/secure/secure_heap.c +++ b/portable/GCC/ARM_CM33/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/GCC/ARM_CM35P/secure/secure_heap.c b/portable/GCC/ARM_CM35P/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/GCC/ARM_CM35P/secure/secure_heap.c +++ b/portable/GCC/ARM_CM35P/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/GCC/ARM_CM55/secure/secure_heap.c b/portable/GCC/ARM_CM55/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/GCC/ARM_CM55/secure/secure_heap.c +++ b/portable/GCC/ARM_CM55/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/GCC/ARM_CM85/secure/secure_heap.c b/portable/GCC/ARM_CM85/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/GCC/ARM_CM85/secure/secure_heap.c +++ b/portable/GCC/ARM_CM85/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/IAR/ARM_CM23/secure/secure_heap.c b/portable/IAR/ARM_CM23/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/IAR/ARM_CM23/secure/secure_heap.c +++ b/portable/IAR/ARM_CM23/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/IAR/ARM_CM33/secure/secure_heap.c b/portable/IAR/ARM_CM33/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/IAR/ARM_CM33/secure/secure_heap.c +++ b/portable/IAR/ARM_CM33/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/IAR/ARM_CM35P/secure/secure_heap.c b/portable/IAR/ARM_CM35P/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/IAR/ARM_CM35P/secure/secure_heap.c +++ b/portable/IAR/ARM_CM35P/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/IAR/ARM_CM55/secure/secure_heap.c b/portable/IAR/ARM_CM55/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/IAR/ARM_CM55/secure/secure_heap.c +++ b/portable/IAR/ARM_CM55/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); { diff --git a/portable/IAR/ARM_CM85/secure/secure_heap.c b/portable/IAR/ARM_CM85/secure/secure_heap.c index 990125a2a70..f3b80df543a 100644 --- a/portable/IAR/ARM_CM85/secure/secure_heap.c +++ b/portable/IAR/ARM_CM85/secure/secure_heap.c @@ -62,6 +62,22 @@ /* Assumes 8bit bytes! */ #define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if adding a and b will result in overflow. */ +#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) ) +#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK ) +#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK ) /*-----------------------------------------------------------*/ /* Allocate the memory for the heap. */ @@ -123,14 +139,6 @@ static BlockLink_t * pxEnd = NULL; static size_t xFreeBytesRemaining = 0U; static size_t xMinimumEverFreeBytesRemaining = 0U; -/** - * @brief Gets set to the top bit of an size_t type. - * - * When this bit in the xBlockSize member of an BlockLink_t structure is set - * then the block belongs to the application. When the bit is free the block is - * still part of the free heap space. - */ -static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ static void prvHeapInit( void ) @@ -175,9 +183,6 @@ static void prvHeapInit( void ) /* Only one block exists - and it covers the entire usable heap space. */ xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ); } /*-----------------------------------------------------------*/ @@ -250,6 +255,7 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxPreviousBlock; BlockLink_t * pxNewBlockLink; void * pvReturn = NULL; + size_t xAdditionalRequiredSize; /* If this is the first call to malloc then the heap will require * initialisation to setup the list of free blocks. */ @@ -262,25 +268,29 @@ void * pvPortMalloc( size_t xWantedSize ) mtCOVERAGE_TEST_MARKER(); } - /* Check the requested block size is not so large that the top bit is set. - * The top bit of the block size member of the BlockLink_t structure is used - * to determine who owns the block - the application or the kernel, so it - * must be free. */ - if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + if( xWantedSize > 0 ) { - /* The wanted size is increased so it can contain a BlockLink_t + /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) { xWantedSize += xHeapStructSize; - /* Ensure that blocks are always aligned to the required number of - * bytes. */ + /* Ensure that blocks are always aligned to the required number + * of bytes. */ if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ - xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) ); - secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 ); + xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ); + + if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } } else { @@ -289,9 +299,20 @@ void * pvPortMalloc( size_t xWantedSize ) } else { - mtCOVERAGE_TEST_MARKER(); + xWantedSize = 0; } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Check the requested block size is not so large that the top bit is set. + * The top bit of the block size member of the BlockLink_t structure is used + * to determine who owns the block - the application or the kernel, so it + * must be free. */ + if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until @@ -355,7 +376,7 @@ void * pvPortMalloc( size_t xWantedSize ) /* The block is being returned - it is allocated and owned by * the application and has no "next" block. */ - pxBlock->xBlockSize |= xBlockAllocatedBit; + secureheapALLOCATE_BLOCK( pxBlock ); pxBlock->pxNextFreeBlock = NULL; } else @@ -409,16 +430,16 @@ void vPortFree( void * pv ) pxLink = ( void * ) puc; /* Check the block is actually allocated. */ - secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); secureportASSERT( pxLink->pxNextFreeBlock == NULL ); - if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer * allocated. */ - pxLink->xBlockSize &= ~xBlockAllocatedBit; + secureheapFREE_BLOCK( pxLink ); secureportDISABLE_NON_SECURE_INTERRUPTS(); {