queue.c: Change some asserts into conditionals and improve overflow checks (#328)

diff --git a/include/stdint.readme b/include/stdint.readme
index b1bb60e..d6c1152 100644
--- a/include/stdint.readme
+++ b/include/stdint.readme
@@ -49,4 +49,8 @@
 typedef long int32_t;

 typedef unsigned long uint32_t;

 

+#ifndef SIZE_MAX

+    #define SIZE_MAX    ( ( size_t ) -1 )

+#endif

+

 #endif /* FREERTOS_STDINT */

diff --git a/queue.c b/queue.c
index 96065d0..f5d8fd7 100644
--- a/queue.c
+++ b/queue.c
@@ -264,12 +264,18 @@
 BaseType_t xQueueGenericReset( QueueHandle_t xQueue,

                                BaseType_t xNewQueue )

 {

+    BaseType_t xReturn = pdPASS;

     Queue_t * const pxQueue = xQueue;

 

     configASSERT( pxQueue );

 

-    taskENTER_CRITICAL();

+    if( ( pxQueue != NULL ) &&

+        ( pxQueue->uxLength >= 1U ) &&

+        /* Check for multiplication overflow. */

+        ( ( SIZE_MAX / pxQueue->uxLength ) >= pxQueue->uxItemSize ) )

     {

+        taskENTER_CRITICAL();

+

         pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */

         pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;

         pxQueue->pcWriteTo = pxQueue->pcHead;

@@ -306,12 +312,18 @@
             vListInitialise( &( pxQueue->xTasksWaitingToSend ) );

             vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );

         }

+        taskEXIT_CRITICAL();

     }

-    taskEXIT_CRITICAL();

+    else

+    {

+        xReturn = pdFAIL;

+    }

+

+    configASSERT( xReturn != pdFAIL );

 

     /* A value is returned for calling semantic consistency with previous

      * versions. */

-    return pdPASS;

+    return xReturn;

 }

 /*-----------------------------------------------------------*/

 

@@ -323,39 +335,38 @@
                                              StaticQueue_t * pxStaticQueue,

                                              const uint8_t ucQueueType )

     {

-        Queue_t * pxNewQueue;

-

-        configASSERT( uxQueueLength > ( UBaseType_t ) 0 );

+        Queue_t * pxNewQueue = NULL;

 

         /* The StaticQueue_t structure and the queue storage area must be

          * supplied. */

-        configASSERT( pxStaticQueue != NULL );

+        configASSERT( pxStaticQueue );

 

-        /* A queue storage area should be provided if the item size is not 0, and

-         * should not be provided if the item size is 0. */

-        configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );

-        configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );

-

-        #if ( configASSERT_DEFINED == 1 )

-            {

-                /* Sanity check that the size of the structure used to declare a

-                 * variable of type StaticQueue_t or StaticSemaphore_t equals the size of

-                 * the real queue and semaphore structures. */

-                volatile size_t xSize = sizeof( StaticQueue_t );

-

-                /* This assertion cannot be branch covered in unit tests */

-                configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */

-                ( void ) xSize;                             /* Keeps lint quiet when configASSERT() is not defined. */

-            }

-        #endif /* configASSERT_DEFINED */

-

-        /* The address of a statically allocated queue was passed in, use it.

-         * The address of a statically allocated storage area was also passed in

-         * but is already set. */

-        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. */

-

-        if( pxNewQueue != NULL )

+        if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&

+            ( pxStaticQueue != NULL ) &&

+            /* A queue storage area should be provided if the item size is not 0, and

+             * should not be provided if the item size is 0. */

+            ( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ) &&

+            ( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ) )

         {

+

+            #if ( configASSERT_DEFINED == 1 )

+                {

+                    /* Sanity check that the size of the structure used to declare a

+                     * variable of type StaticQueue_t or StaticSemaphore_t equals the size of

+                     * the real queue and semaphore structures. */

+                    volatile size_t xSize = sizeof( StaticQueue_t );

+

+                    /* This assertion cannot be branch covered in unit tests */

+                    configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */

+                    ( void ) xSize;                             /* Keeps lint quiet when configASSERT() is not defined. */

+                }

+            #endif /* configASSERT_DEFINED */

+

+            /* The address of a statically allocated queue was passed in, use it.

+             * The address of a statically allocated storage area was also passed in

+             * but is already set. */

+            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. */

+

             #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )

                 {

                     /* Queues can be allocated wither statically or dynamically, so

@@ -369,7 +380,7 @@
         }

         else

         {

-            traceQUEUE_CREATE_FAILED( ucQueueType );

+            configASSERT( pxNewQueue );

             mtCOVERAGE_TEST_MARKER();

         }

 

@@ -385,55 +396,59 @@
                                        const UBaseType_t uxItemSize,

                                        const uint8_t ucQueueType )

     {

-        Queue_t * pxNewQueue;

+        Queue_t * pxNewQueue = NULL;

         size_t xQueueSizeInBytes;

         uint8_t * pucQueueStorage;

 

-        configASSERT( uxQueueLength > ( UBaseType_t ) 0 );

-

-        /* Allocate enough space to hold the maximum number of items that

-         * can be in the queue at any time.  It is valid for uxItemSize to be

-         * zero in the case the queue is used as a semaphore. */

-        xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

-

-        /* Check for multiplication overflow. */

-        configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) );

-

-        /* Check for addition overflow. */

-        configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes );

-

-        /* Allocate the queue and storage area.  Justification for MISRA

-         * deviation as follows:  pvPortMalloc() always ensures returned memory

-         * blocks are aligned per the requirements of the MCU stack.  In this case

-         * pvPortMalloc() must return a pointer that is guaranteed to meet the

-         * alignment requirements of the Queue_t structure - which in this case

-         * is an int8_t *.  Therefore, whenever the stack alignment requirements

-         * are greater than or equal to the pointer to char requirements the cast

-         * is safe.  In other cases alignment requirements are not strict (one or

-         * two bytes). */

-        pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */

-

-        if( pxNewQueue != NULL )

+        if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&

+            /* Check for multiplication overflow. */

+            ( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&

+            /* Check for addition overflow. */

+            ( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) )

         {

-            /* Jump past the queue structure to find the location of the queue

-             * storage area. */

-            pucQueueStorage = ( uint8_t * ) pxNewQueue;

-            pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */

+            /* Allocate enough space to hold the maximum number of items that

+             * can be in the queue at any time.  It is valid for uxItemSize to be

+             * zero in the case the queue is used as a semaphore. */

+            xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

 

-            #if ( configSUPPORT_STATIC_ALLOCATION == 1 )

-                {

-                    /* Queues can be created either statically or dynamically, so

-                     * note this task was created dynamically in case it is later

-                     * deleted. */

-                    pxNewQueue->ucStaticallyAllocated = pdFALSE;

-                }

-            #endif /* configSUPPORT_STATIC_ALLOCATION */

+            /* Allocate the queue and storage area.  Justification for MISRA

+             * deviation as follows:  pvPortMalloc() always ensures returned memory

+             * blocks are aligned per the requirements of the MCU stack.  In this case

+             * pvPortMalloc() must return a pointer that is guaranteed to meet the

+             * alignment requirements of the Queue_t structure - which in this case

+             * is an int8_t *.  Therefore, whenever the stack alignment requirements

+             * are greater than or equal to the pointer to char requirements the cast

+             * is safe.  In other cases alignment requirements are not strict (one or

+             * two bytes). */

+            pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */

 

-            prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );

+            if( pxNewQueue != NULL )

+            {

+                /* Jump past the queue structure to find the location of the queue

+                 * storage area. */

+                pucQueueStorage = ( uint8_t * ) pxNewQueue;

+                pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */

+

+                #if ( configSUPPORT_STATIC_ALLOCATION == 1 )

+                    {

+                        /* Queues can be created either statically or dynamically, so

+                         * note this task was created dynamically in case it is later

+                         * deleted. */

+                        pxNewQueue->ucStaticallyAllocated = pdFALSE;

+                    }

+                #endif /* configSUPPORT_STATIC_ALLOCATION */

+

+                prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );

+            }

+            else

+            {

+                traceQUEUE_CREATE_FAILED( ucQueueType );

+                mtCOVERAGE_TEST_MARKER();

+            }

         }

         else

         {

-            traceQUEUE_CREATE_FAILED( ucQueueType );

+            configASSERT( pxNewQueue );

             mtCOVERAGE_TEST_MARKER();

         }

 

@@ -719,22 +734,28 @@
                                                        const UBaseType_t uxInitialCount,

                                                        StaticQueue_t * pxStaticQueue )

     {

-        QueueHandle_t xHandle;

+        QueueHandle_t xHandle = NULL;

 

-        configASSERT( uxMaxCount != 0 );

-        configASSERT( uxInitialCount <= uxMaxCount );

-

-        xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );

-

-        if( xHandle != NULL )

+        if( ( uxMaxCount != 0 ) &&

+            ( uxInitialCount <= uxMaxCount ) )

         {

-            ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;

+            xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );

 

-            traceCREATE_COUNTING_SEMAPHORE();

+            if( xHandle != NULL )

+            {

+                ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;

+

+                traceCREATE_COUNTING_SEMAPHORE();

+            }

+            else

+            {

+                traceCREATE_COUNTING_SEMAPHORE_FAILED();

+            }

         }

         else

         {

-            traceCREATE_COUNTING_SEMAPHORE_FAILED();

+            configASSERT( xHandle );

+            mtCOVERAGE_TEST_MARKER();

         }

 

         return xHandle;

@@ -748,22 +769,28 @@
     QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,

                                                  const UBaseType_t uxInitialCount )

     {

-        QueueHandle_t xHandle;

+        QueueHandle_t xHandle = NULL;

 

-        configASSERT( uxMaxCount != 0 );

-        configASSERT( uxInitialCount <= uxMaxCount );

-

-        xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );

-

-        if( xHandle != NULL )

+        if( ( uxMaxCount != 0 ) &&

+            ( uxInitialCount <= uxMaxCount ) )

         {

-            ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;

+            xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );

 

-            traceCREATE_COUNTING_SEMAPHORE();

+            if( xHandle != NULL )

+            {

+                ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;

+

+                traceCREATE_COUNTING_SEMAPHORE();

+            }

+            else

+            {

+                traceCREATE_COUNTING_SEMAPHORE_FAILED();

+            }

         }

         else

         {

-            traceCREATE_COUNTING_SEMAPHORE_FAILED();

+            configASSERT( xHandle );

+            mtCOVERAGE_TEST_MARKER();

         }

 

         return xHandle;