Re: [PATCH v3 1/9] worktree: stop being overly intimate with run_command() internals
- From
Eric Sunshine <sunshine@sunshineco.com>
- Date
- Nov 26, 2021, 09:48 UTC
- Message-ID
- <CAPig+cRi6SeuV7k_+9JCcnf79daLZp5B=EyHK-KxC1VGN0B4ig@mail.gmail.com>
- In-Reply-To
- <patch-v3-1.9-1c3f9de33ad-20211125T224833Z-avarab@gmail.com>
On Thu, Nov 25, 2021 at 5:52 PM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
Show 13 quoted lines
> From: Eric Sunshine <sunshine@sunshineco.com> > > add_worktree() reuses a `child_process` for three run_command() > invocations, but to do so, it has overly-intimate knowledge of > run-command.c internals. In particular, it knows that it must reset > child_process::argv to NULL for each subsequent invocation[*] in order > for start_command() to latch the newly-populated child_process::args for > each invocation, even though this behavior is not a part of the > documented API. Beyond having overly-intimate knowledge of run-command.c > internals, the reuse of one `child_process` for three run_command() > invocations smells like an unnecessary micro-optimization. Therefore, > stop sharing one `child_process` and instead use a new one for each > run_command() call.
If people feel uncomfortable with the way this patch shadows `cp` in nested blocks, an alternative would be to call child_process_init(&cp) to reuse the existing `cp`, similar to the fix[1] applied to pager.c when reusing a `child_process`. I don't feel strongly about it either way.
[1]: https://lore.kernel.org/git/20211125000239.2336-1-ematsumiya@suse.de/
Show 46 quoted lines
> [*] If child_process::argv is not reset to NULL, then subsequent
> run_command() invocations will instead incorrectly access a dangling
> pointer to freed memory which had been allocated by child_process::args
> on the previous run. This is due to the following code in
> start_command():
>
> if (!cmd->argv)
> cmd->argv = cmd->args.v;
>
> Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> builtin/worktree.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index d22ece93e1a..9edd3e2829b 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -355,8 +355,8 @@ static int add_worktree(const char *path, const char *refname,
> goto done;
>
> if (opts->checkout) {
> - cp.argv = NULL;
> - strvec_clear(&cp.args);
> + struct child_process cp = CHILD_PROCESS_INIT;
> + cp.git_cmd = 1;
> strvec_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
> if (opts->quiet)
> strvec_push(&cp.args, "--quiet");
> @@ -385,12 +385,11 @@ static int add_worktree(const char *path, const char *refname,
> const char *hook = find_hook("post-checkout");
> if (hook) {
> const char *env[] = { "GIT_DIR", "GIT_WORK_TREE", NULL };
> - cp.git_cmd = 0;
> + struct child_process cp = CHILD_PROCESS_INIT;
> cp.no_stdin = 1;
> cp.stdout_to_stderr = 1;
> cp.dir = path;
> cp.env = env;
> - cp.argv = NULL;
> cp.trace2_hook_name = "post-checkout";
> strvec_pushl(&cp.args, absolute_path(hook),
> oid_to_hex(null_oid()),
> --
> 2.34.1.838.g779e9098efb