summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <freddy77@gmail.com>2023-11-07 10:51:24 +0000
committerFrediano Ziglio <freddy77@gmail.com>2023-11-07 10:52:04 +0000
commitf7136a01dfda31151c21069fa33750ef8e799638 (patch)
treedd4f7d3eceb1e506e04e529e0fce73627d37905d
parent4cd1f492352afcced8233b2cec44f1d28a961830 (diff)
Avoid possible bug with strict aliasing
Tell code we are breaking strict aliasing. Most of the time works but with some strong optimisation compiler could produce not working code because of the aliasing breakage. Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
-rw-r--r--tun.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/tun.c b/tun.c
index 4ab93b3..5d0a30e 100644
--- a/tun.c
+++ b/tun.c
@@ -43,6 +43,12 @@
#define uh_sum check
#endif
+#if defined(__GNUC__)
+# define MAY_ALIAS __attribute__((__may_alias__))
+#else
+# define MAY_ALIAS
+#endif
+
static int tun_fd = -1;
static int tun_fd_back = -1;
static int remote_sock = -1;
@@ -345,13 +351,14 @@ reduce_cksum(unsigned sum)
static unsigned
cksum(const void *pkt, size_t len, unsigned int start)
{
- const uint16_t *data = (const uint16_t *) pkt;
+ typedef union MAY_ALIAS { uint16_t full; uint8_t part; } u16;
+ const u16 *data = (const u16 *) pkt;
unsigned sum = start;
- for (; len >= 2; len -= 2)
- sum += *data++;
+ for (; len >= 2; len -= 2, ++data)
+ sum += data->full;
if (len)
- sum += ntohs(*((const uint8_t *)data) << 8);
+ sum += ntohs(data->part << 8);
sum = reduce_cksum(sum);
sum = reduce_cksum(sum);
return sum;