https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78408
Bug ID: 78408 Summary: Aggressive optimization of zeroing results in incorrect behavior Product: gcc Version: 6.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: npmccallum at redhat dot com Target Milestone: --- $ gcc -v Using built-in specs. COLLECT_GCC=/usr/bin/gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/6.2.1/lto-wrapper Target: x86_64-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux Thread model: posix gcc version 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC) Compiling the file uses this command line: gcc -DPACKAGE_NAME=\"clevis\" -DPACKAGE_TARNAME=\"clevis\" -DPACKAGE_VERSION=\"1\" -DPACKAGE_STRING=\"clevis\ 1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"clevis\" -DVERSION=\"1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -I. -Wall -Wextra -Werror -Wstrict-aliasing -Wchar-subscripts -Wformat-security -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wshadow -Wsign-compare -Wstrict-prototypes -Wtype-limits -Wno-missing-field-initializers -Wno-unused-parameter -pthread -I/usr/include/udisks2 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -DCLEVIS_CMD_DIR=/usr/libexec/clevis -g -O2 -MT clevis-luks-udisks2.o -MD -MP -MF $depbase.Tpo -c -o clevis-luks-udisks2.o clevis-luks-udisks2.c The relevant code is here[1]. GCC sees that "pkt_t key" might go out of scope and therefore optimizes out the zeroing of the struct that occurs at the end of the for loop iteration. However, key doesn't go out of scope during loop iteration. Thus, on subsequent loops the struct is used presuming that it contains a zero value but it doesn't. This means that (what I take to be) perfectly valid ISO C behaves in strange ways. In particular, the bug that arises is as follows. When load_jwe() fails[2], the (incorrectly) presumed zeroed key struct is sent[3] to the client. The end result is that an invalid key (the previous successful one) is sent when an empty UDP packet should be sent. GCC should detect that "pkt_t key" is not going out of scope and should zero it as requested rather than invalidly optimizing out this statement. Clang does not have this bug, so there is at least one example of a compiler doing the right thing. [1] - https://github.com/latchset/clevis/blob/6834b02b390771a97775dcfa26f85243f3a0195d/udisks2/clevis-luks-udisks2.c#L446 [2] - https://github.com/latchset/clevis/blob/6834b02b390771a97775dcfa26f85243f3a0195d/udisks2/clevis-luks-udisks2.c#L455 [3] - https://github.com/latchset/clevis/blob/6834b02b390771a97775dcfa26f85243f3a0195d/udisks2/clevis-luks-udisks2.c#L469