Improve heap bounds checking in pvPortMalloc

This commit is contained in:
Cobus van Eeden 2020-12-05 15:54:11 -08:00
parent 68ca3a9b2a
commit d00ae49986
4 changed files with 68 additions and 30 deletions

View file

@ -77,8 +77,13 @@ void * pvPortMalloc( size_t xWantedSize )
{ {
if( xWantedSize & portBYTE_ALIGNMENT_MASK ) if( xWantedSize & portBYTE_ALIGNMENT_MASK )
{ {
/* Byte alignment required. */ /* Byte alignment required, check for overflow first */
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize )
{
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
} else {
xWantedSize = 0;
}
} }
} }
#endif #endif
@ -91,8 +96,9 @@ void * pvPortMalloc( size_t xWantedSize )
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
} }
/* Check there is enough room left for the allocation. */ /* Check there is enough room left for the allocation and. */
if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && if( ( xWantedSize > 0 ) && /* valid size */
( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ) /* Check for overflow. */ ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ) /* Check for overflow. */
{ {
/* Return the next free byte then increment the index past this /* Return the next free byte then increment the index past this

View file

@ -125,28 +125,36 @@ void * pvPortMalloc( size_t xWantedSize )
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* If this is the first call to malloc then the heap will require /* If this is the first call to malloc then the heap will require
* initialisation to setup the list of free blocks. */ * initialisation to setup the list of free blocks. */
if( xHeapHasBeenInitialised == pdFALSE ) if( xHeapHasBeenInitialised == pdFALSE )
{ {
prvHeapInit(); prvHeapInit();
xHeapHasBeenInitialised = pdTRUE; xHeapHasBeenInitialised = pdTRUE;
} }
/* 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. */ * structure in addition to the requested amount of bytes. */
if( xWantedSize > 0 ) if( xWantedSize > 0 )
{ {
xWantedSize += heapSTRUCT_SIZE; /* Ensure xWantedSize will never wrap after adjustment, even if we need
* an alignment adjustment */
/* Ensure that blocks are always aligned to the required number of bytes. */ if ( xWantedSize < ( SIZE_MAX - heapSTRUCT_SIZE - portBYTE_ALIGNMENT - 1) )
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 )
{ {
/* Byte alignment required. */ xWantedSize += heapSTRUCT_SIZE;
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
/* Ensure that blocks are always aligned to the required number of bytes. */
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 )
{
/* Byte alignment required. */
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
}
} else {
/* If the requested size is too large to handle we force an error */
xWantedSize = 0;
} }
} }
if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) ) if( xWantedSize > 0 )
{ {
/* Blocks are stored in byte order - traverse the list from the start /* Blocks are stored in byte order - traverse the list from the start
* (smallest) block until one of adequate size is found. */ * (smallest) block until one of adequate size is found. */

View file

@ -140,19 +140,35 @@ void * pvPortMalloc( size_t xWantedSize )
* structure in addition to the requested amount of bytes. */ * structure in addition to the requested amount of bytes. */
if( xWantedSize > 0 ) if( xWantedSize > 0 )
{ {
xWantedSize += xHeapStructSize; /* Check for overflow */
if ( ( xWantedSize + xHeapStructSize ) > xWantedSize )
{
xWantedSize += xHeapStructSize;
/* Ensure that blocks are always aligned to the required number /* Ensure that blocks are always aligned to the required number
* of bytes. */ * of bytes. */
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
{
/* Byte alignment required. (check for overflow again) */
if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) )
> xWantedSize )
{
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
}
else
{
xWantedSize = 0;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{ {
/* Byte alignment required. */ xWantedSize = 0;
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
} }
else else
@ -160,7 +176,7 @@ void * pvPortMalloc( size_t xWantedSize )
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) if( ( xWantedSize > 0 ) && ( xWantedSize < xFreeBytesRemaining ) )
{ {
/* Traverse the list from the start (lowest address) block until /* Traverse the list from the start (lowest address) block until
* one of adequate size is found. */ * one of adequate size is found. */

View file

@ -150,7 +150,7 @@ void * pvPortMalloc( size_t xWantedSize )
{ {
/* The wanted size is increased so it can contain a BlockLink_t /* The wanted size is increased so it can contain a BlockLink_t
* structure in addition to the requested amount of bytes. */ * structure in addition to the requested amount of bytes. */
if( xWantedSize > 0 ) if( ( xWantedSize > 0 ) && ( ( xWantedSize + xHeapStructSize ) > xWantedSize ) )
{ {
xWantedSize += xHeapStructSize; xWantedSize += xHeapStructSize;
@ -159,7 +159,15 @@ void * pvPortMalloc( size_t xWantedSize )
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
{ {
/* Byte alignment required. */ /* Byte alignment required. */
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) >
xWantedSize )
{
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
}
else
{
xWantedSize = 0;
}
} }
else else
{ {
@ -168,10 +176,10 @@ void * pvPortMalloc( size_t xWantedSize )
} }
else else
{ {
mtCOVERAGE_TEST_MARKER(); xWantedSize = 0;
} }
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) if( ( xWantedSize > 0 ) && ( xWantedSize < xFreeBytesRemaining ) )
{ {
/* Traverse the list from the start (lowest address) block until /* Traverse the list from the start (lowest address) block until
* one of adequate size is found. */ * one of adequate size is found. */