Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misra rule 11.3, 11.4 suppression and 4.6 fix #512

Merged
merged 20 commits into from
Jul 12, 2022
Merged

Misra rule 11.3, 11.4 suppression and 4.6 fix #512

merged 20 commits into from
Jul 12, 2022

Conversation

xuelix
Copy link
Member

@xuelix xuelix commented Jul 2, 2022

Description

Test Steps

Related Issue

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@xuelix xuelix requested a review from a team as a code owner July 2, 2022 23:53
shubnil
shubnil previously approved these changes Jul 6, 2022
Copy link
Contributor

@paulbartell paulbartell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explanation for Rule 11.3 deviations needs to explain how proper alignment is maintained.

@xuelix xuelix requested a review from paulbartell July 7, 2022 23:35
@xuelix xuelix changed the title Misra rule 11.4 suppression and 4.6 fix Misra rule 11.3, 11.4 suppression and 4.6 fix Jul 8, 2022
n9wxu
n9wxu previously approved these changes Jul 8, 2022
@@ -616,6 +616,11 @@
{
xDHCPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );

/* MISRA Rule 11.4 warns about casting pointer to a different type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which cast is being referenced here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change the wording here. It's a conversion.

@xuelix xuelix requested a review from paulbartell July 11, 2022 23:52
Copy link
Contributor

@htibosch htibosch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/* MISRA C-2012 Rule 11.3 warns about casting pointer type
* to a different data type. The struct to be casted to is
* defined as a packed struct. The cast won't cause misalignment. */
/* coverity[misra_c_2012_rule_11_3_violation] */

Thank you for these additions, I approve it.

A small comment for those who wonder why we ignore MISRA C-2012 Rule 11.3:

The TCP/IP library receives and sends all sorts of packets: ARP, TCP/IP, UDP/IP, DHCP, DNS etc. These packets are stored in a buffer pucEthernetBuffer which is always aligned in the same manner: a four-byte alignment plus two bytes. The reason for this is that the Ethernet header is 14 (12+2) bytes long. So after the Ethernet header, the words and shorts are properly aligned.

It is convenient (and also efficient) to access a word as a word, as in pxIPHeader->ulDestinationIPAddress.

There is one alignment exception, which is in the ARP header: the sender protocol address, or ucSenderProtocolAddress[4], is declared as an array of 4 bytes. It falls on a 2-byte alignment.

In some situations, in stead of copying shorts and words, byte access will be done like here in FreeRTOS_DNS_Parser.c :

#define vSetField16( pxBase, xType, xField, usValue )                                                        \
    {                                                                                                        \
        ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 );    \
        ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xffU ); \
    }

which works independent from the endianness.

In other situations, where the alignment is unknown, memcpy() is used to access data.

When structs are copied, memcpy() should be used, and not a struct assignment as in xCopy = xOrg. The latter may lead to an alignment exception. The compiler can be mistaken about the alignment of the structs.

I recommend to use the compiler flags -fno-builtin-memcpy and -fno-builtin-memset. In some situations, compilers make the wrong assumptions about alignment, when replacing a 4-byte memcpy() with a 32-byte assignment.

The use of packed structs is necessary, the alignment in the declarations must be guaranteed the same as in the packets on the wire.

The FreeRTOS+TCP library has been tested and used on a wide variety of platforms: little and big endian, and on both 32- and 64-bit platforms.

Hein

@paulbartell
Copy link
Contributor

/* MISRA C-2012 Rule 11.3 warns about casting pointer type
* to a different data type. The struct to be casted to is
* defined as a packed struct. The cast won't cause misalignment. */
/* coverity[misra_c_2012_rule_11_3_violation] */

Thank you for these additions, I approve it.

A small comment for those who wonder why we ignore MISRA C-2012 Rule 11.3:

The TCP/IP library receives and sends all sorts of packets: ARP, TCP/IP, UDP/IP, DHCP, DNS etc. These packets are stored in a buffer pucEthernetBuffer which is always aligned in the same manner: a four-byte alignment plus two bytes. The reason for this is that the Ethernet header is 14 (12+2) bytes long. So after the Ethernet header, the words and shorts are properly aligned.

It is convenient (and also efficient) to access a word as a word, as in pxIPHeader->ulDestinationIPAddress.

There is one alignment exception, which is in the ARP header: the sender protocol address, or ucSenderProtocolAddress[4], is declared as an array of 4 bytes. It falls on a 2-byte alignment.

In some situations, in stead of copying shorts and words, byte access will be done like here in FreeRTOS_DNS_Parser.c :

#define vSetField16( pxBase, xType, xField, usValue )                                                        \
    {                                                                                                        \
        ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 );    \
        ( ( uint8_t * ) ( pxBase ) )[ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xffU ); \
    }

which works independent from the endianness.

In other situations, where the alignment is unknown, memcpy() is used to access data.

When structs are copied, memcpy() should be used, and not a struct assignment as in xCopy = xOrg. The latter may lead to an alignment exception. The compiler can be mistaken about the alignment of the structs.

I recommend to use the compiler flags -fno-builtin-memcpy and -fno-builtin-memset. In some situations, compilers make the wrong assumptions about alignment, when replacing a 4-byte memcpy() with a 32-byte assignment.

The use of packed structs is necessary, the alignment in the declarations must be guaranteed the same as in the packets on the wire.

The FreeRTOS+TCP library has been tested and used on a wide variety of platforms: little and big endian, and on both 32- and 64-bit platforms.

Hein

When a struct is declared as packed, that struct and it's members are treated as byte-aligned. This means that a compiler should not make any alignment assumptions when copying or assigning members of the struct.

@xuelix xuelix merged commit ab51932 into FreeRTOS:main Jul 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants