Fix aliasing violations in ip6_and

Accessing uint8_t[16] through a different type is an aliasing violation, i.e. undefined behaviour.

Use memcpy to copy the bytes out, then AND them, then memcpy back in.
The actual memcpy calls will be optimized away, but doing it this way avoids undefined behaviour.
This commit is contained in:
Jonathan Wakely 2022-06-08 16:29:44 +01:00 committed by GitHub
parent 4a47e535f0
commit 6adaf5ca27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -105,16 +105,12 @@ static inline const struct in6_addr *mask_from_bitcount6(uint32_t zct)
// result = a & b
static void ip6_and(const struct in6_addr *a, const struct in6_addr *b, struct in6_addr *result)
{
// POSSIBLE GCC COMPILER BUG . when using uint64_t and -O2/-O3 optimizations this function gets inlined with the wrong code and produces wrong results
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__NO_INLINE__)
((uint32_t*)result->s6_addr)[0] = ((uint32_t*)a->s6_addr)[0] & ((uint32_t*)b->s6_addr)[0];
((uint32_t*)result->s6_addr)[1] = ((uint32_t*)a->s6_addr)[1] & ((uint32_t*)b->s6_addr)[1];
((uint32_t*)result->s6_addr)[2] = ((uint32_t*)a->s6_addr)[2] & ((uint32_t*)b->s6_addr)[2];
((uint32_t*)result->s6_addr)[3] = ((uint32_t*)a->s6_addr)[3] & ((uint32_t*)b->s6_addr)[3];
#else
((uint64_t*)result->s6_addr)[0] = ((uint64_t*)a->s6_addr)[0] & ((uint64_t*)b->s6_addr)[0];
((uint64_t*)result->s6_addr)[1] = ((uint64_t*)a->s6_addr)[1] & ((uint64_t*)b->s6_addr)[1];
#endif
uint64_t a_addr[2], b_addr[2];
memcpy(a_addr, a->s6_addr, 16);
memcpy(b_addr, b->s6_addr, 16);
a_addr[0] &= b_addr[0];
a_addr[1] &= b_addr[1];
memcpy(result->s6_addr, a_addr, 16);
}
static void rtrim(char *s)