https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87167
Bug ID: 87167 Summary: strlen of stack-allocated zero-length array misoptimized in GCC 8 Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: matti.niemenmaa+gccbugs at iki dot fi Target Milestone: --- Created attachment 44636 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44636&action=edit Preprocessed source Unpreprocessed source code for illustration, reduced from UADE 2.13 (Unix Amiga Delitracker Emulator): #include <stdio.h> #include <string.h> struct uade_msg { int x; char data[0]; } __attribute__((packed)); int main(void) { char commandbuf[4096] = {0}; struct uade_msg *um = (struct uade_msg *)commandbuf; strcpy(um->data, "foobar"); printf("%s has strlen %zu\n", um->data, strlen((const char *)um->data)); printf("%s has strlen %zu\n", um->data, strlen((const char *)um->data)); } When compiled with -O2 -fno-strict-aliasing on GCC 8.2.0, the output of the resulting program on my x86-64 machine is: foobar has strlen 6 foobar has strlen 0 GCC 7.3.1 and 5.4.1 show a strlen of 6 on both output lines. (As does clang 6.0.1, for what it's worth.) Looking at a snippet of the assembly, around the printf calls: movl $6, %edx leaq .LC0(%rip), %rdi movl $1651470182, 4(%rsp) call printf@PLT xorl %edx, %edx xorl %eax, %eax movq %rbx, %rsi leaq .LC0(%rip), %rdi call printf@PLT It looks like GCC 8.2.0 has optimized away both strlen calls, but replaced each with a different value. Based on a cursory inspection, GCC 7.3.1 and 5.4.1 optimize away the first strlen call and inline the second (and clang 6.0.1 doesn't do anything to the first but re-uses the result instead of doing another call). Replacing the `char data[0]` with `char data[]` seems to cause GCC 8.2.0 to behave the same way as 7.3.1 and 5.4.1, resulting in an output of 6 on both lines. Using calloc instead of the stack allocation does the same. It's been a while since I had to worry about the aliasing rules in C so I'm not entirely sure whether this is code is invalid or not, but regardless, I would expect to always see a result of 6 here with -fno-strict-aliasing. Full output from gcc uade.c -O2 -fno-strict-aliasing -Wall -Wextra -v -save-temps: Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto Thread model: posix gcc version 8.2.0 (GCC) COLLECT_GCC_OPTIONS='-O2' '-fno-strict-aliasing' '-Wall' '-Wextra' '-v' '-save-temps' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -E -quiet -v uade.c -mtune=generic -march=x86-64 -Wall -Wextra -fno-strict-aliasing -O2 -fpch-preprocess -o uade.i ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include /usr/local/include /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-O2' '-fno-strict-aliasing' '-Wall' '-Wextra' '-v' '-save-temps' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -fpreprocessed uade.i -quiet -dumpbase uade.c -mtune=generic -march=x86-64 -auxbase uade -O2 -Wall -Wextra -version -fno-strict-aliasing -o uade.s GNU C17 (GCC) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C17 (GCC) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 374c644ab4db4fa02e30fa5669d43e86 COLLECT_GCC_OPTIONS='-O2' '-fno-strict-aliasing' '-Wall' '-Wextra' '-v' '-save-temps' '-mtune=generic' '-march=x86-64' as -v --64 -o uade.o uade.s GNU assembler version 2.31.1 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.31.1 COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-O2' '-fno-strict-aliasing' '-Wall' '-Wextra' '-v' '-save-temps' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper -plugin-opt=-fresolution=uade.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../.. uade.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib/crtn.o COLLECT_GCC_OPTIONS='-O2' '-fno-strict-aliasing' '-Wall' '-Wextra' '-v' '-save-temps' '-mtune=generic' '-march=x86-64'