Skip to content

Commit 8b8df3d

Browse files
pcercueiQuzarDC
authored andcommitted
net: Fix checksum, part 3
The code was breaking aliasing rules when called from net_ipv4_checksum_pseudo(), as the struct address was indirectly casted to a uint16_t pointer, causing GCC to not bother emit the proper code for the undefined behaviour. Address this issue by using a locally defined uint16_t type that is allowed to alias. Signed-off-by: Paul Cercueil <paul@crapouillou.net>
1 parent 73f25c9 commit 8b8df3d

1 file changed

Lines changed: 3 additions & 1 deletion

File tree

kernel/net/net_ipv4.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ static inline uint16_t checksum_one(uint16_t val, uint16_t sum) {
3535

3636
/* Perform an IP-style checksum on a block of data */
3737
uint16_t __pure net_ipv4_checksum(const uint8_t *data, size_t bytes, uint16_t sum) {
38+
typedef uint16_t __attribute__((may_alias)) alias_u16_t;
39+
3840
/* Make sure we don't do any unaligned memory accesses */
3941
if((uintptr_t)data & 1) {
4042
sum = checksum_one(*data, sum);
@@ -44,7 +46,7 @@ uint16_t __pure net_ipv4_checksum(const uint8_t *data, size_t bytes, uint16_t su
4446

4547
/* Compute checksum two bytes at a time */
4648
for(; bytes > 1; bytes -= 2, data += 2)
47-
sum = checksum_one(*(const uint16_t *)data, sum);
49+
sum = checksum_one(*(const alias_u16_t *)data, sum);
4850

4951
/* Handle the last byte, if we have an odd byte count */
5052
if(bytes)

0 commit comments

Comments
 (0)