The following simplified standalone C code illustrates this bug. If we compile it with and without O2 flag, the executions are different.
The comments at the beginning of the following code has GCC information, compiling commands, and execution outputs. ==== Example C Code ===== /* GCC Version: gcc -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: ../gcc-4.1.1/configure --prefix=/usr --libexecdir=/usr/lib --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-c99 --enable-long-long --enable-clocale=gnu --enable-languages=c,c++ --disable-multilib --disable-libstdcxx-pch Thread model: posix gcc version 4.1.1 Compile commands: gcc -o test test.c; gcc -O2 -o O2_test test.c <cr> Execution outputs: ./test; ./O2_test <cr> Output: ./test: Bug[1] 2001:d::2/64 matches 2001:d::1. ./O2_test: Bug[0] 2001:c::1/64 matches 2001:d::1. */ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <netinet/in.h> typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; static inline int __ipv6_prefix_equal(const u32 *a1, const u32 *a2, unsigned int prefixlen) { unsigned pdw, pbi; pdw = prefixlen >> 5; if (pdw && memcmp(a1, a2, pdw << 2)) return 0; pbi = prefixlen & 0x1f; if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) return 0; return 1; } static inline int ipv6_prefix_equal(const struct in6_addr *a1, const struct in6_addr *a2, unsigned int prefixlen) { return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32, prefixlen); } static inline int ipv6_addr_any(const struct in6_addr *a) { return ((a->s6_addr32[0] | a->s6_addr32[1] | a->s6_addr32[2] | a->s6_addr32[3] ) == 0); } struct temp { unsigned int ipv6_prefixlen; struct in6_addr ipv6_addr; struct in6_addr ipv6_lladdr; } bug[2]; struct in6_addr target; int find_bug (int link_local_nexthop) { int i; for (i = 0 ; i <= 1; i++) { if (ipv6_addr_any(&bug[i].ipv6_addr) && !link_local_nexthop) continue; if (ipv6_addr_any(&bug[i].ipv6_lladdr) && link_local_nexthop) continue; if (ipv6_prefix_equal(&bug[i].ipv6_addr, &target, bug[i].ipv6_prefixlen)) { return i; } } return -1; } int main(int argc, char ** argv) { int i = -1; char ipv6[3][256]; strcpy(ipv6[0], "2001:c::1"); strcpy(ipv6[1], "2001:d::2"); strcpy(ipv6[2], "2001:d::1"); inet_pton(AF_INET6, ipv6[0], &bug[0].ipv6_addr); inet_pton(AF_INET6, "fe80:c::1", &bug[0].ipv6_lladdr); bug[0].ipv6_prefixlen = 64; inet_pton(AF_INET6, ipv6[1], &bug[1].ipv6_addr); inet_pton(AF_INET6, "fe80:2001::1", &bug[1].ipv6_lladdr); bug[1].ipv6_prefixlen = 64; inet_pton(AF_INET6, ipv6[2], &target); i = find_bug(0); if (i == -1) printf("No match found.\n"); else printf("%10s: Bug[%d] %s/%u matches %s.\n", argv[0], i, ipv6[i], bug[i].ipv6_prefixlen, ipv6[2]); return 0; } -- Summary: Compilings with and with O2 flag lead to different execution results Product: gcc Version: 4.1.1 Status: UNCONFIRMED Severity: critical Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: tlin at a10networks dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40312