From 7c73cb3ace6659df58ec2382b8d47bb521dad886 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 27 Feb 2018 21:08:57 +0100 Subject: [PATCH] Work around a GCC bug that causes inet_checksum() to give wrong results. Valgrind reports the following bug: ==24877== Conditional jump or move depends on uninitialised value(s) ==24877== at 0x12283E: inet_checksum (route.c:80) ==24877== by 0x12283E: route_ipv6_unreachable (route.c:315) ==24877== by 0x1236AC: route_ipv6 (route.c:751) ==24877== by 0x1236AC: route (route.c:1160) ==24877== by 0x113DE0: receive_tcppacket (net_packet.c:493) ==24877== by 0x1119D4: receive_meta (meta.c:315) ==24877== by 0x113288: handle_meta_connection_data (net.c:287) ==24877== by 0x11A091: handle_meta_io (net_socket.c:491) ==24877== by 0x10FB0C: event_loop (event.c:370) ==24877== by 0x11362E: main_loop (net.c:489) ==24877== by 0x10CACA: main (tincd.c:551) Clearing the variable pseudo in route_ipv6_unreachable removes this error, but the resulting checksum is still bad. If one instead adds a dummy write that depends on checksum, the error goes away and the checksum is correct. --- src/route.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/route.c b/src/route.c index a3e92020..4d712795 100644 --- a/src/route.c +++ b/src/route.c @@ -59,6 +59,7 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr); #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif +volatile int dummy; static timeout_t age_subnets_timeout; /* RFC 1071 */ @@ -80,6 +81,11 @@ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { checksum = (checksum & 0xFFFF) + (checksum >> 16); } + // Work around a compiler optimization bug. + if(checksum) { + dummy = 1; + } + return ~checksum; } -- 2.20.1