From b9d630d6ca60812b48b7c15bdb4fa36797ddf32e Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Wed, 4 Dec 2024 21:35:16 -0500 Subject: [PATCH] Fix #10574 - environment pointer sometimes changes before exec, causing segfault in child process. --- std/process.d | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/std/process.d b/std/process.d index bd98e7312ac..cb193bb75ff 100644 --- a/std/process.d +++ b/std/process.d @@ -149,7 +149,7 @@ private version (Darwin) { extern(C) char*** _NSGetEnviron() nothrow; - const(char**) getEnvironPtr() @trusted + const(char**) getEnvironPtr() @trusted @nogc nothrow { return *_NSGetEnviron; } @@ -158,7 +158,7 @@ private { // Made available by the C runtime: extern(C) extern __gshared const char** environ; - const(char**) getEnvironPtr() @trusted + const(char**) getEnvironPtr() @trusted @nogc nothrow { return environ; } @@ -1119,7 +1119,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args, } // Execute program. - core.sys.posix.unistd.execve(argz[0], argz.ptr, envz); + core.sys.posix.unistd.execve(argz[0], argz.ptr, envz is null ? getEnvironPtr : envz); // If execution fails, exit as quickly as possible. abortOnError(forkPipeOut, InternalError.exec, .errno); @@ -1421,7 +1421,7 @@ private Pid spawnProcessWin(scope const(char)[] commandLine, // on the form "name=value", optionally adding those of the current process' // environment strings that are not present in childEnv. If the parent's // environment should be inherited without modification, this function -// returns environ directly. +// returns null. version (Posix) private const(char*)* createEnv(const string[string] childEnv, bool mergeWithParentEnv) @@ -1431,7 +1431,7 @@ private const(char*)* createEnv(const string[string] childEnv, auto environ = getEnvironPtr; if (mergeWithParentEnv) { - if (childEnv.length == 0) return environ; + if (childEnv.length == 0) return null; while (environ[parentEnvLength] != null) ++parentEnvLength; } @@ -1461,16 +1461,7 @@ version (Posix) @system unittest assert(e1 != null && *e1 == null); auto e2 = createEnv(null, true); - assert(e2 != null); - int i = 0; - auto environ = getEnvironPtr; - for (; environ[i] != null; ++i) - { - assert(e2[i] != null); - import core.stdc.string : strcmp; - assert(strcmp(e2[i], environ[i]) == 0); - } - assert(e2[i] == null); + assert(e2 == null); auto e3 = createEnv(["foo" : "bar", "hello" : "world"], false); assert(e3 != null && e3[0] != null && e3[1] != null && e3[2] == null);