In order to avoid allocation between 'fork()' and 'exec()' the argv array used in the exec call is prepared prior to forking the process. Signed-off-by: Brandon Williams <bmwill@xxxxxxxxxx> --- run-command.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/run-command.c b/run-command.c index 682bc3ca5..2514b54bc 100644 --- a/run-command.c +++ b/run-command.c @@ -226,18 +226,6 @@ static const char **prepare_shell_cmd(struct argv_array *out, const char **argv) } #ifndef GIT_WINDOWS_NATIVE -static int execv_shell_cmd(const char **argv) -{ - struct argv_array nargv = ARGV_ARRAY_INIT; - prepare_shell_cmd(&nargv, argv); - trace_argv_printf(nargv.argv, "trace: exec:"); - sane_execvpe(nargv.argv[0], (char **)nargv.argv, NULL); - argv_array_clear(&nargv); - return -1; -} -#endif - -#ifndef GIT_WINDOWS_NATIVE static int child_notifier = -1; static void notify_parent(void) @@ -377,9 +365,20 @@ int start_command(struct child_process *cmd) #ifndef GIT_WINDOWS_NATIVE { int notify_pipe[2]; + struct argv_array argv = ARGV_ARRAY_INIT; + if (pipe(notify_pipe)) notify_pipe[0] = notify_pipe[1] = -1; + if (cmd->git_cmd) { + argv_array_push(&argv, "git"); + argv_array_pushv(&argv, cmd->argv); + } else if (cmd->use_shell) { + prepare_shell_cmd(&argv, cmd->argv); + } else { + argv_array_pushv(&argv, cmd->argv); + } + cmd->pid = fork(); failed_errno = errno; if (!cmd->pid) { @@ -442,12 +441,9 @@ int start_command(struct child_process *cmd) unsetenv(*cmd->env); } } - if (cmd->git_cmd) - execv_git_cmd(cmd->argv); - else if (cmd->use_shell) - execv_shell_cmd(cmd->argv); - else - sane_execvpe(cmd->argv[0], (char *const*) cmd->argv, NULL); + + sane_execvpe(argv.argv[0], (char *const*) argv.argv, NULL); + if (errno == ENOENT) { if (!cmd->silent_exec_failure) error("cannot run %s: %s", cmd->argv[0], @@ -480,6 +476,8 @@ int start_command(struct child_process *cmd) cmd->pid = -1; } close(notify_pipe[0]); + + argv_array_clear(&argv); } #else { -- 2.12.2.715.g7642488e1d-goog