Skip to content

Commit

Permalink
Suppress MISRA C:2012 rule 11.5 deviations (#878)
Browse files Browse the repository at this point in the history
* Suppress MISRA C:2012 rule 11.5 deviations by comment also remove this rule in global config

---------

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Ubuntu <ubuntu@ip-172-31-34-245.ap-northeast-1.compute.internal>
Co-authored-by: Rahul Kar <karahulx@amazon.com>
Co-authored-by: Soren Ptak <ptaksoren@gmail.com>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
  • Loading branch information
6 people authored Dec 6, 2023
1 parent cd5c774 commit 84c0047
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 75 deletions.
82 changes: 58 additions & 24 deletions MISRA.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,72 @@ grep 'MISRA Ref 8.4.1' . -rI

#### Rule 8.4

MISRA C:2012 Rule 8.4: A compatible declaration shall be visible when an
object or function with external linkage is defined.

_Ref 8.4.1_

- MISRA C:2012 Rule 8.4: A compatible declaration shall be visible when an
object or function with external linkage is defined.
This rule requires that a compatible declaration is made available
in a header file when an object with external linkage is defined.
pxCurrentTCB(s) is defined with external linkage but it is only
referenced from the assembly code in the port files. Therefore, adding
a declaration in header file is not useful as the assembly code will
still need to declare it separately.
- This rule requires that a compatible declaration is made available
in a header file when an object with external linkage is defined.
pxCurrentTCB(s) is defined with external linkage but it is only
referenced from the assembly code in the port files. Therefore, adding
a declaration in header file is not useful as the assembly code will
still need to declare it separately.


#### Rule 11.3

MISRA C:2012 Rule 11.3: A cast shall not be performed between a pointer to
object type and a pointer to a different object type.

_Ref 11.3.1_
- This rule prohibits casting a pointer to object into a pointer to a
different object because it may result in an incorrectly aligned pointer,
leading to undefined behavior. Even if the casting produces a correctly
aligned pointer, the behavior may be still undefined if the pointer is
used to access an object. FreeRTOS deliberately creates external aliases
for all the kernel object types (StaticEventGroup_t, StaticQueue_t,
StaticStreamBuffer_t, StaticTimer_t and StaticTask_t) for data hiding
purposes. The internal object types and the corresponding external
aliases are guaranteed to have the same size and alignment which is
checked using configASSERT.


#### Rule 11.5

MISRA C:2012 Rule 11.5: A conversion should not be performed from pointer to
void into pointer to object.
This rule prohibits conversion of a pointer to void into a pointer to
object because it may result in an incorrectly aligned pointer leading
to undefined behavior.

- MISRA C:2012 Rule 11.3: A cast shall not be performed between a pointer to
object type and a pointer to a different object type.
This rule prohibits casting a pointer to object into a pointer to a
different object because it may result in an incorrectly aligned pointer,
leading to undefined behavior. Even if the casting produces a correctly
aligned pointer, the behavior may be still undefined if the pointer is
used to access an object. FreeRTOS deliberately creates external aliases
for all the kernel object types (StaticEventGroup_t, StaticQueue_t,
StaticStreamBuffer_t, StaticTimer_t and StaticTask_t) for data hiding
purposes. The internal object types and the corresponding external
aliases are guaranteed to have the same size and alignment which is
checked using configASSERT.
_Ref 11.5.1_
- The memory blocks returned by pvPortMalloc() are guaranteed to meet the
architecture alignment requirements specified by portBYTE_ALIGNMENT.
The casting of the pointer to void returned by pvPortMalloc() is,
therefore, safe because it is guaranteed to be aligned.

_Ref 11.5.2_
- The conversion from a pointer to void into a pointer to EventGroup_t is
safe because it is a pointer to EventGroup_t, which is returned to the
application at the time of event group creation for data hiding
purposes.

_Ref 11.5.3_
- The conversion from a pointer to void in list macros for list item owner
is safe because the type of the pointer stored and retrieved is the
same.

_Ref 11.5.4_
- The conversion from a pointer to void into a pointer to EventGroup_t is
safe because it is a pointer to EventGroup_t, which is passed as a
parameter to the xTimerPendFunctionCallFromISR API when the callback is
pended.

_Ref 11.5.5_
- The conversion from a pointer to void into a pointer to uint8_t is safe
because data storage buffers are implemented as uint8_t arrays for the
ease of sizing, alignment and access.


### MISRA configuration
Expand Down Expand Up @@ -81,10 +119,6 @@ Copy below content to `misra.conf` to run Coverity on FreeRTOS-Kernel.
{
deviation: "Rule 8.7",
reason: "API functions are not used by the library outside of the files they are defined; however, they must be externally visible in order to be used by an application."
},
{
deviation: "Rule 11.5",
reason: "Allow casts from `void *`. List owner, pvOwner, is stored as `void *` and are cast to various types for use in functions."
}
]
}
Expand Down
3 changes: 3 additions & 0 deletions croutine.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex );

/* Allocate the memory that will store the co-routine control block. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );

if( pxCoRoutine )
Expand Down
39 changes: 21 additions & 18 deletions event_groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,

traceENTER_xEventGroupCreate();

/* Allocate the event group. 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 EventGroup_t structure - which (if you
* follow it through) is the alignment requirements of the TickType_t type
* (EventBits_t being of TickType_t itself). Therefore, whenever the
* stack alignment requirements are greater than or equal to the
* TickType_t alignment requirements the cast is safe. In other cases,
* where the natural word size of the architecture is less than
* sizeof( TickType_t ), the TickType_t variables will be accessed in two
* or more reads operations, and the alignment requirements is only that
* of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );

if( pxEventBits != NULL )
{
Expand Down Expand Up @@ -749,7 +739,10 @@ void vEventGroupSetBitsCallback( void * pvEventGroup,
{
traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );

( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
/* MISRA Ref 11.5.4 [Callback function parameter] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );

traceRETURN_vEventGroupSetBitsCallback();
}
Expand All @@ -762,7 +755,10 @@ void vEventGroupClearBitsCallback( void * pvEventGroup,
{
traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );

( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
/* MISRA Ref 11.5.4 [Callback function parameter] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );

traceRETURN_vEventGroupClearBitsCallback();
}
Expand Down Expand Up @@ -831,7 +827,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
{
UBaseType_t xReturn;
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */

/* MISRA Ref 11.5.2 [Opaque pointer] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup;

traceENTER_uxEventGroupGetNumber( xEventGroup );

Expand Down Expand Up @@ -859,7 +859,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
{
traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );

( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
/* MISRA Ref 11.5.2 [Opaque pointer] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;

traceRETURN_vEventGroupSetNumber();
}
Expand Down
14 changes: 4 additions & 10 deletions queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,16 +517,10 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
* zero in the case the queue is used as a semaphore. */
xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize );

/* 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. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );

if( pxNewQueue != NULL )
{
Expand Down
25 changes: 20 additions & 5 deletions stream_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,14 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,

if( pvAllocatedMemory != NULL )
{
prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pvAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */
( ( uint8_t * ) pvAllocatedMemory ) + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pvAllocatedMemory, /* Structure at the start of the allocated memory. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( ( uint8_t * ) pvAllocatedMemory ) + sizeof( StreamBuffer_t ), /* Storage area follows. */
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags,
Expand All @@ -391,7 +397,10 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,

traceRETURN_xStreamBufferGenericCreate( pvAllocatedMemory );

return ( StreamBufferHandle_t ) pvAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
return ( StreamBufferHandle_t ) pvAllocatedMemory;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
Expand Down Expand Up @@ -940,7 +949,10 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
if( xDataLengthBytes != ( size_t ) 0 )
{
/* Write the data to the buffer. */
pxStreamBuffer->xHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes, xNextHead ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alignment and access. */
/* MISRA Ref 11.5.5 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxStreamBuffer->xHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes, xNextHead );
}

return xDataLengthBytes;
Expand Down Expand Up @@ -1204,7 +1216,10 @@ static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
if( xCount != ( size_t ) 0 )
{
/* Read the actual data and update the tail to mark the data as officially consumed. */
pxStreamBuffer->xTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xCount, xNextTail ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */
/* MISRA Ref 11.5.5 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxStreamBuffer->xTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xCount, xNextTail );
}

return xCount;
Expand Down
Loading

0 comments on commit 84c0047

Please # to comment.