https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116642
Bug ID: 116642 Summary: miscompilation involving vfork child. Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: joshudson at gmail dot com Target Milestone: --- Created attachment 59073 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59073&action=edit main reproduction source file GCC Version: gcc (Debian 12.2.0-14) 12.2.0 Build Command: gcc -o nutty -Wall -Wl,-T,minipie.ld -Wl,--no-dynamic-linker -pie -nostdlib -nostartfiles -O3 -s -fpic -fno-asynchronous-unwind-tables -ffreestanding package.s nutty.i The resulting binary doesn't work: the first first array member passed to execve() is out of bounds. This is easily observed with strace -f: execve("./nutty", ["./nutty"], 0x7fffc4882e28 /* 41 vars */) = 0 open("uid.db", O_RDWR|O_CREAT, 0600) = 3 flock(3, LOCK_EX) = 0 read(3, "", 4096) = 0 vfork(strace: Process 19097 attached <unfinished ...> [pid 19097] execve("/bin/false", [0x82d, "-md", "/u/Ubbbb/home/Ubbbb", "-k", "/u/Ubbbb/etc/skel", "-s", "", "-u", "60000", "-g", "urun", "Ubbbb"], NULL) = -1 EFAULT (Bad address) [pid 19097] exit(0) = ? [pid 19096] <... vfork resumed>) = 19097 [pid 19097] +++ exited with 0 +++ --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=19097, si_uid=1000, si_status=0, si_utime=0, si_stime=0} --- wait4(19097, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 19097 exit(14) = ? +++ exited with 14 +++ (0x82d is bogus...) I have had enormous difficulty reducing this; it behaves very much like there needs to be a certain weight to the code in the function or the miscompilation disappears. It's almost like it has something with the xmm variables but I haven't been able to locate the definite problem in the assembly file. This code has already been reduced far beyond sensibility and won't make sense to you--it's no longer doing something meaningful. Either of the following small changes result in the code working: 1) move the declaration of argv[] outside the if vfork() statement 2) put a writeblock function call inside the vfork() if block before execve. I only tried it after the argv[] declaration; never before. For some reason the compiler thinks _exit() returns; this is probably a good thing otherwise there's a chance it would overlap argv[] with something vital. There's been some discussion online (unfortunately marred by a vfork opponent) as to whether or not this is the signature of undefined behavior; however no undefined behavior has been found and we can't come up with a remotely plausible hypothesis how undefined behavior can cause this particular malfunction; all workable hypotheses would fail after a successful execve not upon calling it.