summaryrefslogtreecommitdiff
path: root/src/job.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2022-09-25 13:29:59 -0400
committerPaul Smith <psmith@gnu.org>2022-09-25 16:57:31 -0400
commitc4e232e44f00be75ba58bc5f12e7562a62028fe9 (patch)
tree447d2ed4ac0886545837bf97994d985199953c71 /src/job.c
parentaa99e810a9158e8c0ff8bb024c3dacc2722d0f18 (diff)
downloadmake-git-c4e232e44f00be75ba58bc5f12e7562a62028fe9.tar.gz
Always restore global environ if we use vfork
We may change the global environ variable in the child; when using vfork() this also sets it in the parent. Preserve the parent's environ in child_execute_job() so it takes effect for all callers. Reported by Denis Excoffier <bug-tar@Denis-Excoffier.org> Root cause found by Martin Dorey <Martin.Dorey@hitachivantara.com> * src/job.c (start_job_command): Remove save/restore of the parent environment. (child_execute_job): Add save/restore of the parent environment, if we use vfork(). * tests/scripts/functions/shell: Add a test the crashes if we don't reset environ after we run $(shell ...).
Diffstat (limited to 'src/job.c')
-rw-r--r--src/job.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/src/job.c b/src/job.c
index d12a9138..19f27977 100644
--- a/src/job.c
+++ b/src/job.c
@@ -1460,9 +1460,6 @@ start_job_command (struct child *child)
#endif /* !VMS */
{
/* Fork the child process. */
-
- char **parent_environ;
-
run_local:
block_sigs ();
@@ -1473,14 +1470,11 @@ start_job_command (struct child *child)
#else
- parent_environ = environ;
-
jobserver_pre_child (flags & COMMANDS_RECURSE);
child->pid = child_execute_job ((struct childbase *)child,
child->good_stdin, argv);
- environ = parent_environ; /* Restore value child may have clobbered. */
jobserver_post_child (flags & COMMANDS_RECURSE);
#endif /* !VMS */
@@ -1503,7 +1497,7 @@ start_job_command (struct child *child)
char *cmdline = argv[0];
/* We don't have a way to pass environment to 'system',
so we need to save and restore ours, sigh... */
- char **parent_environ = environ;
+ char **parent_env = environ;
environ = child->environment;
@@ -1518,7 +1512,7 @@ start_job_command (struct child *child)
dos_command_running = 1;
proc_return = system (cmdline);
- environ = parent_environ;
+ environ = parent_env;
execute_by_shell = 0; /* for the next time */
}
else
@@ -2299,9 +2293,16 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
#if !defined(USE_POSIX_SPAWN)
- pid = vfork();
- if (pid != 0)
- return pid;
+ {
+ /* The child may clobber environ so remember ours and restore it. */
+ char **parent_env = environ;
+ pid = vfork ();
+ if (pid != 0)
+ {
+ environ = parent_env;
+ return pid;
+ }
+ }
/* We are the child. */
unblock_all_sigs ();
@@ -2552,7 +2553,9 @@ exec_command (char **argv, char **envp)
errno = ENOEXEC;
# else
- /* Run the program. */
+
+ /* Run the program. Don't use execvpe() as we want the search for argv[0]
+ to use the new PATH, but execvpe() searches before resetting PATH. */
environ = envp;
execvp (argv[0], argv);