Skip to content

Commit 8e2f723

Browse files
authored
queue.c: Change some asserts into conditionals and improve overflow checks (#328)
1 parent a1b918c commit 8e2f723

File tree

2 files changed

+123
-92
lines changed

2 files changed

+123
-92
lines changed

include/stdint.readme

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,8 @@ typedef unsigned short uint16_t;
4949
typedef long int32_t;
5050
typedef unsigned long uint32_t;
5151

52+
#ifndef SIZE_MAX
53+
#define SIZE_MAX ( ( size_t ) -1 )
54+
#endif
55+
5256
#endif /* FREERTOS_STDINT */

queue.c

Lines changed: 119 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,18 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
264264
BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
265265
BaseType_t xNewQueue )
266266
{
267+
BaseType_t xReturn = pdPASS;
267268
Queue_t * const pxQueue = xQueue;
268269

269270
configASSERT( pxQueue );
270271

271-
taskENTER_CRITICAL();
272+
if( ( pxQueue != NULL ) &&
273+
( pxQueue->uxLength >= 1U ) &&
274+
/* Check for multiplication overflow. */
275+
( ( SIZE_MAX / pxQueue->uxLength ) >= pxQueue->uxItemSize ) )
272276
{
277+
taskENTER_CRITICAL();
278+
273279
pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
274280
pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
275281
pxQueue->pcWriteTo = pxQueue->pcHead;
@@ -306,12 +312,18 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
306312
vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
307313
vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
308314
}
315+
taskEXIT_CRITICAL();
309316
}
310-
taskEXIT_CRITICAL();
317+
else
318+
{
319+
xReturn = pdFAIL;
320+
}
321+
322+
configASSERT( xReturn != pdFAIL );
311323

312324
/* A value is returned for calling semantic consistency with previous
313325
* versions. */
314-
return pdPASS;
326+
return xReturn;
315327
}
316328
/*-----------------------------------------------------------*/
317329

@@ -323,39 +335,38 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
323335
StaticQueue_t * pxStaticQueue,
324336
const uint8_t ucQueueType )
325337
{
326-
Queue_t * pxNewQueue;
327-
328-
configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
338+
Queue_t * pxNewQueue = NULL;
329339

330340
/* The StaticQueue_t structure and the queue storage area must be
331341
* supplied. */
332-
configASSERT( pxStaticQueue != NULL );
342+
configASSERT( pxStaticQueue );
333343

334-
/* A queue storage area should be provided if the item size is not 0, and
335-
* should not be provided if the item size is 0. */
336-
configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );
337-
configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );
338-
339-
#if ( configASSERT_DEFINED == 1 )
340-
{
341-
/* Sanity check that the size of the structure used to declare a
342-
* variable of type StaticQueue_t or StaticSemaphore_t equals the size of
343-
* the real queue and semaphore structures. */
344-
volatile size_t xSize = sizeof( StaticQueue_t );
344+
if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
345+
( pxStaticQueue != NULL ) &&
346+
/* A queue storage area should be provided if the item size is not 0, and
347+
* should not be provided if the item size is 0. */
348+
( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ) &&
349+
( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ) )
350+
{
345351

346-
/* This assertion cannot be branch covered in unit tests */
347-
configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */
348-
( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
349-
}
350-
#endif /* configASSERT_DEFINED */
352+
#if ( configASSERT_DEFINED == 1 )
353+
{
354+
/* Sanity check that the size of the structure used to declare a
355+
* variable of type StaticQueue_t or StaticSemaphore_t equals the size of
356+
* the real queue and semaphore structures. */
357+
volatile size_t xSize = sizeof( StaticQueue_t );
358+
359+
/* This assertion cannot be branch covered in unit tests */
360+
configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */
361+
( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
362+
}
363+
#endif /* configASSERT_DEFINED */
351364

352-
/* The address of a statically allocated queue was passed in, use it.
353-
* The address of a statically allocated storage area was also passed in
354-
* but is already set. */
355-
pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
365+
/* The address of a statically allocated queue was passed in, use it.
366+
* The address of a statically allocated storage area was also passed in
367+
* but is already set. */
368+
pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
356369

357-
if( pxNewQueue != NULL )
358-
{
359370
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
360371
{
361372
/* Queues can be allocated wither statically or dynamically, so
@@ -369,7 +380,7 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
369380
}
370381
else
371382
{
372-
traceQUEUE_CREATE_FAILED( ucQueueType );
383+
configASSERT( pxNewQueue );
373384
mtCOVERAGE_TEST_MARKER();
374385
}
375386

@@ -385,55 +396,59 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
385396
const UBaseType_t uxItemSize,
386397
const uint8_t ucQueueType )
387398
{
388-
Queue_t * pxNewQueue;
399+
Queue_t * pxNewQueue = NULL;
389400
size_t xQueueSizeInBytes;
390401
uint8_t * pucQueueStorage;
391402

392-
configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
393-
394-
/* Allocate enough space to hold the maximum number of items that
395-
* can be in the queue at any time. It is valid for uxItemSize to be
396-
* zero in the case the queue is used as a semaphore. */
397-
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
398-
399-
/* Check for multiplication overflow. */
400-
configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) );
401-
402-
/* Check for addition overflow. */
403-
configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes );
404-
405-
/* Allocate the queue and storage area. Justification for MISRA
406-
* deviation as follows: pvPortMalloc() always ensures returned memory
407-
* blocks are aligned per the requirements of the MCU stack. In this case
408-
* pvPortMalloc() must return a pointer that is guaranteed to meet the
409-
* alignment requirements of the Queue_t structure - which in this case
410-
* is an int8_t *. Therefore, whenever the stack alignment requirements
411-
* are greater than or equal to the pointer to char requirements the cast
412-
* is safe. In other cases alignment requirements are not strict (one or
413-
* two bytes). */
414-
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */
415-
416-
if( pxNewQueue != NULL )
417-
{
418-
/* Jump past the queue structure to find the location of the queue
419-
* storage area. */
420-
pucQueueStorage = ( uint8_t * ) pxNewQueue;
421-
pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
422-
423-
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
424-
{
425-
/* Queues can be created either statically or dynamically, so
426-
* note this task was created dynamically in case it is later
427-
* deleted. */
428-
pxNewQueue->ucStaticallyAllocated = pdFALSE;
429-
}
430-
#endif /* configSUPPORT_STATIC_ALLOCATION */
403+
if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
404+
/* Check for multiplication overflow. */
405+
( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&
406+
/* Check for addition overflow. */
407+
( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) )
408+
{
409+
/* Allocate enough space to hold the maximum number of items that
410+
* can be in the queue at any time. It is valid for uxItemSize to be
411+
* zero in the case the queue is used as a semaphore. */
412+
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
413+
414+
/* Allocate the queue and storage area. Justification for MISRA
415+
* deviation as follows: pvPortMalloc() always ensures returned memory
416+
* blocks are aligned per the requirements of the MCU stack. In this case
417+
* pvPortMalloc() must return a pointer that is guaranteed to meet the
418+
* alignment requirements of the Queue_t structure - which in this case
419+
* is an int8_t *. Therefore, whenever the stack alignment requirements
420+
* are greater than or equal to the pointer to char requirements the cast
421+
* is safe. In other cases alignment requirements are not strict (one or
422+
* two bytes). */
423+
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */
424+
425+
if( pxNewQueue != NULL )
426+
{
427+
/* Jump past the queue structure to find the location of the queue
428+
* storage area. */
429+
pucQueueStorage = ( uint8_t * ) pxNewQueue;
430+
pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
431+
432+
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
433+
{
434+
/* Queues can be created either statically or dynamically, so
435+
* note this task was created dynamically in case it is later
436+
* deleted. */
437+
pxNewQueue->ucStaticallyAllocated = pdFALSE;
438+
}
439+
#endif /* configSUPPORT_STATIC_ALLOCATION */
431440

432-
prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
441+
prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
442+
}
443+
else
444+
{
445+
traceQUEUE_CREATE_FAILED( ucQueueType );
446+
mtCOVERAGE_TEST_MARKER();
447+
}
433448
}
434449
else
435450
{
436-
traceQUEUE_CREATE_FAILED( ucQueueType );
451+
configASSERT( pxNewQueue );
437452
mtCOVERAGE_TEST_MARKER();
438453
}
439454

@@ -719,22 +734,28 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
719734
const UBaseType_t uxInitialCount,
720735
StaticQueue_t * pxStaticQueue )
721736
{
722-
QueueHandle_t xHandle;
723-
724-
configASSERT( uxMaxCount != 0 );
725-
configASSERT( uxInitialCount <= uxMaxCount );
726-
727-
xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
737+
QueueHandle_t xHandle = NULL;
728738

729-
if( xHandle != NULL )
739+
if( ( uxMaxCount != 0 ) &&
740+
( uxInitialCount <= uxMaxCount ) )
730741
{
731-
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
742+
xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
732743

733-
traceCREATE_COUNTING_SEMAPHORE();
744+
if( xHandle != NULL )
745+
{
746+
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
747+
748+
traceCREATE_COUNTING_SEMAPHORE();
749+
}
750+
else
751+
{
752+
traceCREATE_COUNTING_SEMAPHORE_FAILED();
753+
}
734754
}
735755
else
736756
{
737-
traceCREATE_COUNTING_SEMAPHORE_FAILED();
757+
configASSERT( xHandle );
758+
mtCOVERAGE_TEST_MARKER();
738759
}
739760

740761
return xHandle;
@@ -748,22 +769,28 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
748769
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
749770
const UBaseType_t uxInitialCount )
750771
{
751-
QueueHandle_t xHandle;
752-
753-
configASSERT( uxMaxCount != 0 );
754-
configASSERT( uxInitialCount <= uxMaxCount );
755-
756-
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
772+
QueueHandle_t xHandle = NULL;
757773

758-
if( xHandle != NULL )
774+
if( ( uxMaxCount != 0 ) &&
775+
( uxInitialCount <= uxMaxCount ) )
759776
{
760-
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
777+
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
761778

762-
traceCREATE_COUNTING_SEMAPHORE();
779+
if( xHandle != NULL )
780+
{
781+
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
782+
783+
traceCREATE_COUNTING_SEMAPHORE();
784+
}
785+
else
786+
{
787+
traceCREATE_COUNTING_SEMAPHORE_FAILED();
788+
}
763789
}
764790
else
765791
{
766-
traceCREATE_COUNTING_SEMAPHORE_FAILED();
792+
configASSERT( xHandle );
793+
mtCOVERAGE_TEST_MARKER();
767794
}
768795

769796
return xHandle;

0 commit comments

Comments
 (0)