From: Arran Cudbard-Bell Date: Sun, 13 Jul 2025 15:15:42 +0000 (-0600) Subject: Fix unaligned access in DHCPv4 "get_option" on MacOS X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=804e9d2413c65edb68e0511311bf048b6fe186b4;p=thirdparty%2Ffreeradius-server.git Fix unaligned access in DHCPv4 "get_option" on MacOS --- diff --git a/src/protocols/dhcpv4/packet.c b/src/protocols/dhcpv4/packet.c index 6d0d0d6390..41e91354b7 100644 --- a/src/protocols/dhcpv4/packet.c +++ b/src/protocols/dhcpv4/packet.c @@ -43,10 +43,25 @@ uint8_t const *fr_dhcpv4_packet_get_option(dhcp_packet_t const *packet, size_t p if (packet_size < MIN_PACKET_SIZE) return NULL; + /* + * This is needed for UBSAN on MacOS, that doesn't + * allow misaligned accesses. Because the packet + * structure is flat, we don't need to deref the + * packet pointer at any point, we just need to + * calculate the offsets relative to the pointer + * value and use those... Whatever actually deals + * with the option is just expecting a uint8_t *. + */ +#define ALIGNED_ACCESS(packet, field) \ + (uint8_t const *)packet + offsetof(dhcp_packet_t, field) + where = 0; size = packet_size - offsetof(dhcp_packet_t, options); - data = &packet->options[where]; + /* + * Alignment fix. We can't just deref a pointer + */ + data = ALIGNED_ACCESS(packet, options); while (where < size) { if (data[0] == 0) { /* padding */ where++; @@ -56,14 +71,14 @@ uint8_t const *fr_dhcpv4_packet_get_option(dhcp_packet_t const *packet, size_t p if (data[0] == 255) { /* end of options */ if ((field == DHCP_OPTION_FIELD) && (overload & DHCP_FILE_FIELD)) { - data = packet->file; + data = ALIGNED_ACCESS(packet, file); where = 0; size = sizeof(packet->file); field = DHCP_FILE_FIELD; continue; } else if ((field == DHCP_FILE_FIELD || field == DHCP_OPTION_FIELD) && (overload & DHCP_SNAME_FIELD)) { - data = packet->sname; + data = ALIGNED_ACCESS(packet, sname); where = 0; size = sizeof(packet->sname); field = DHCP_SNAME_FIELD;