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