Skip to content

Commit 1823bea

Browse files
peffgitster
authored andcommitted
git_connect: use argv_array
This avoids magic numbers when we allocate fixed-size argv arrays, and makes it more obvious that we are not overflowing. It is also the first step to fixing a memory leak. When git_connect returns a child_process struct, the argv array in the struct is dynamically allocated, but the individual strings are not (they are either owned elsewhere, or are freed). Later, in finish_connect, we free the array but leave the strings alone. This works for the child_process created by git_connect, but if we use transport_take_over, we may also end up with a child_process created by transport-helper's get_helper. In that case, the strings are freshly allocated, and we would want to free them. However, we have no idea in finish_connect which type we have. By consistently using run-command's internal argv-array, we do not have to worry about this issue at all; finish_command takes care of it for us, and we can drop our manual free entirely. Note that this actually makes the get_helper leak slightly worse; now we are leaking both the strings and the array. But when we adjust it in a future patch, that leak will go away entirely. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5eb7f7e commit 1823bea

File tree

1 file changed

+10
-18
lines changed

1 file changed

+10
-18
lines changed

connect.c

+10-18
Original file line numberDiff line numberDiff line change
@@ -534,22 +534,18 @@ static int git_use_proxy(const char *host)
534534
static struct child_process *git_proxy_connect(int fd[2], char *host)
535535
{
536536
const char *port = STR(DEFAULT_GIT_PORT);
537-
const char **argv;
538537
struct child_process *proxy;
539538

540539
get_host_and_port(&host, &port);
541540

542-
argv = xmalloc(sizeof(*argv) * 4);
543-
argv[0] = git_proxy_command;
544-
argv[1] = host;
545-
argv[2] = port;
546-
argv[3] = NULL;
547541
proxy = xcalloc(1, sizeof(*proxy));
548-
proxy->argv = argv;
542+
argv_array_push(&proxy->args, git_proxy_command);
543+
argv_array_push(&proxy->args, host);
544+
argv_array_push(&proxy->args, port);
549545
proxy->in = -1;
550546
proxy->out = -1;
551547
if (start_command(proxy))
552-
die("cannot start proxy %s", argv[0]);
548+
die("cannot start proxy %s", git_proxy_command);
553549
fd[0] = proxy->out; /* read from proxy stdout */
554550
fd[1] = proxy->in; /* write to proxy stdin */
555551
return proxy;
@@ -663,7 +659,6 @@ struct child_process *git_connect(int fd[2], const char *url,
663659
char *hostandport, *path;
664660
struct child_process *conn = &no_fork;
665661
enum protocol protocol;
666-
const char **arg;
667662
struct strbuf cmd = STRBUF_INIT;
668663

669664
/* Without this we cannot rely on waitpid() to tell
@@ -707,7 +702,6 @@ struct child_process *git_connect(int fd[2], const char *url,
707702
sq_quote_buf(&cmd, path);
708703

709704
conn->in = conn->out = -1;
710-
conn->argv = arg = xcalloc(7, sizeof(*arg));
711705
if (protocol == PROTO_SSH) {
712706
const char *ssh = getenv("GIT_SSH");
713707
int putty = ssh && strcasestr(ssh, "plink");
@@ -718,22 +712,21 @@ struct child_process *git_connect(int fd[2], const char *url,
718712

719713
if (!ssh) ssh = "ssh";
720714

721-
*arg++ = ssh;
715+
argv_array_push(&conn->args, ssh);
722716
if (putty && !strcasestr(ssh, "tortoiseplink"))
723-
*arg++ = "-batch";
717+
argv_array_push(&conn->args, "-batch");
724718
if (port) {
725719
/* P is for PuTTY, p is for OpenSSH */
726-
*arg++ = putty ? "-P" : "-p";
727-
*arg++ = port;
720+
argv_array_push(&conn->args, putty ? "-P" : "-p");
721+
argv_array_push(&conn->args, port);
728722
}
729-
*arg++ = ssh_host;
723+
argv_array_push(&conn->args, ssh_host);
730724
} else {
731725
/* remove repo-local variables from the environment */
732726
conn->env = local_repo_env;
733727
conn->use_shell = 1;
734728
}
735-
*arg++ = cmd.buf;
736-
*arg = NULL;
729+
argv_array_push(&conn->args, cmd.buf);
737730

738731
if (start_command(conn))
739732
die("unable to fork");
@@ -759,7 +752,6 @@ int finish_connect(struct child_process *conn)
759752
return 0;
760753

761754
code = finish_command(conn);
762-
free(conn->argv);
763755
free(conn);
764756
return code;
765757
}

0 commit comments

Comments
 (0)