https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106624

--- Comment #8 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
I think I understand now why it's such a mysterious failure. gcc uses putenv()
incorrectly!

I think the real bug was introduced in: commit 1270ccda70ca09f7d4 "Factor out
jobserver_active_p.".

It's gist is the change from `xputenv (concat ("MAKEFLAGS=", dup, NULL));` to
`xputenv (jinfo.skipped_makeflags.c_str ());`.

The difference here is what happens with memory allocated to be put into
putenv().

putenv() is an odd API as it does not copy data, it just interns the pointer:


// $ cat a.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char arr[1000] = "FOO=1234";

int main() {
    putenv(arr);
    printf("getenv(FOO)='%s'\n", getenv("FOO"));
    sprintf(arr + strlen("FOO="), "!!!!");
    printf("getenv(FOO)='%s'\n", getenv("FOO"));
}

Thus `xputenv (jinfo.skipped_makeflags.c_str ());` gets clobbered with garbage
as soon as string is freed and reallocated. I think commit 53e3b2bf16a486c
"lto: support --jobserver-style=fifo for recent GNU make" only happens to
tickle string reallocation as it does things with more std::strings.

As a hack it looks like the following is enough to build a gcc for me:

--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -9182,7 +9182,7 @@ driver::detect_jobserver () const
 {
   jobserver_info jinfo;
   if (!jinfo.is_active && !jinfo.skipped_makeflags.empty ())
-    xputenv (jinfo.skipped_makeflags.c_str ());
+    xputenv (xstrdup(jinfo.skipped_makeflags.c_str ()));
 }

 /* Determine what the exit code of the driver should be.  */

Not sure what should be used instead for proper memory management.

Reply via email to