diff --git a/connect.c b/connect.c index 3a12562146..20054e4d0f 100644 --- a/connect.c +++ b/connect.c @@ -502,12 +502,18 @@ struct child_process *git_connect(int fd[2], const char *url_orig, c = ':'; } + /* + * Don't do destructive transforms with git:// as that + * protocol code does '[]' dewrapping of its own. + */ if (host[0] == '[') { end = strchr(host + 1, ']'); if (end) { - *end = 0; + if (protocol != PROTO_GIT) { + *end = 0; + host++; + } end++; - host++; } else end = host; } else diff --git a/daemon.c b/daemon.c index 360635eb1c..6c2bd97713 100644 --- a/daemon.c +++ b/daemon.c @@ -399,6 +399,33 @@ static char *xstrdup_tolower(const char *str) return dup; } +static void parse_host_and_port(char *hostport, char **host, + char **port) +{ + if (*hostport == '[') { + char *end; + + end = strchr(hostport, ']'); + if (!end) + die("Invalid reqeuest ('[' without ']')"); + *end = '\0'; + *host = hostport + 1; + if (!end[1]) + *port = NULL; + else if (end[1] == ':') + *port = end + 2; + else + die("Garbage after end of host part"); + } else { + *host = hostport; + *port = strrchr(hostport, ':'); + if (*port) { + *port = '\0'; + ++*port; + } + } +} + /* * Read the host as supplied by the client connection. */ @@ -415,11 +442,10 @@ static void parse_host_arg(char *extra_args, int buflen) vallen = strlen(val) + 1; if (*val) { /* Split : at colon. */ - char *host = val; - char *port = strrchr(host, ':'); + char *host; + char *port; + parse_host_and_port(val, &host, &port); if (port) { - *port = 0; - port++; free(tcp_port); tcp_port = xstrdup(port); }