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.

Reply via email to