Merge branch 'jk/connect-symref-info-leak-fix' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 13 Jun 2017 20:27:05 +0000 (13:27 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 13 Jun 2017 20:27:05 +0000 (13:27 -0700)
Leakfix.

* jk/connect-symref-info-leak-fix:
connect.c: fix leak in parse_one_symref_info()

1  2 
connect.c
diff --combined connect.c
index cd21a1b6f725fc80e40759a8f9b26450633df6a8,8af002bf0fadcee5619f3773d7014af178e6d5e5..c72b1d1151744c5e7c7b82f453892a1bc9b26021
+++ b/connect.c
@@@ -71,7 -71,7 +71,7 @@@ static void parse_one_symref_info(struc
            check_refname_format(target, REFNAME_ALLOW_ONELEVEL))
                /* "symref=bogus:pair */
                goto reject;
-       item = string_list_append(symref, sym);
+       item = string_list_append_nodup(symref, sym);
        item->util = target;
        return;
  reject:
@@@ -111,8 -111,8 +111,8 @@@ static void annotate_refs_with_symref_i
   */
  struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
                              struct ref **list, unsigned int flags,
 -                            struct sha1_array *extra_have,
 -                            struct sha1_array *shallow_points)
 +                            struct oid_array *extra_have,
 +                            struct oid_array *shallow_points)
  {
        struct ref **orig_list = list;
  
                                die("protocol error: expected shallow sha-1, got '%s'", arg);
                        if (!shallow_points)
                                die("repository on the other end cannot be shallow");
 -                      sha1_array_append(shallow_points, old_oid.hash);
 +                      oid_array_append(shallow_points, &old_oid);
                        continue;
                }
  
                }
  
                if (extra_have && !strcmp(name, ".have")) {
 -                      sha1_array_append(extra_have, old_oid.hash);
 +                      oid_array_append(extra_have, &old_oid);
                        continue;
                }
  
@@@ -691,70 -691,6 +691,70 @@@ static const char *get_ssh_command(void
        return NULL;
  }
  
 +static int override_ssh_variant(int *port_option, int *needs_batch)
 +{
 +      char *variant;
 +
 +      variant = xstrdup_or_null(getenv("GIT_SSH_VARIANT"));
 +      if (!variant &&
 +          git_config_get_string("ssh.variant", &variant))
 +              return 0;
 +
 +      if (!strcmp(variant, "plink") || !strcmp(variant, "putty")) {
 +              *port_option = 'P';
 +              *needs_batch = 0;
 +      } else if (!strcmp(variant, "tortoiseplink")) {
 +              *port_option = 'P';
 +              *needs_batch = 1;
 +      } else {
 +              *port_option = 'p';
 +              *needs_batch = 0;
 +      }
 +      free(variant);
 +      return 1;
 +}
 +
 +static void handle_ssh_variant(const char *ssh_command, int is_cmdline,
 +                             int *port_option, int *needs_batch)
 +{
 +      const char *variant;
 +      char *p = NULL;
 +
 +      if (override_ssh_variant(port_option, needs_batch))
 +              return;
 +
 +      if (!is_cmdline) {
 +              p = xstrdup(ssh_command);
 +              variant = basename(p);
 +      } else {
 +              const char **ssh_argv;
 +
 +              p = xstrdup(ssh_command);
 +              if (split_cmdline(p, &ssh_argv) > 0) {
 +                      variant = basename((char *)ssh_argv[0]);
 +                      /*
 +                       * At this point, variant points into the buffer
 +                       * referenced by p, hence we do not need ssh_argv
 +                       * any longer.
 +                       */
 +                      free(ssh_argv);
 +              } else {
 +                      free(p);
 +                      return;
 +              }
 +      }
 +
 +      if (!strcasecmp(variant, "plink") ||
 +          !strcasecmp(variant, "plink.exe"))
 +              *port_option = 'P';
 +      else if (!strcasecmp(variant, "tortoiseplink") ||
 +               !strcasecmp(variant, "tortoiseplink.exe")) {
 +              *port_option = 'P';
 +              *needs_batch = 1;
 +      }
 +      free(p);
 +}
 +
  /*
   * This returns a dummy child_process if the transport protocol does not
   * need fork(2), or a struct child_process object if it does.  Once done,
@@@ -833,8 -769,7 +833,8 @@@ struct child_process *git_connect(int f
                conn->in = conn->out = -1;
                if (protocol == PROTO_SSH) {
                        const char *ssh;
 -                      int putty = 0, tortoiseplink = 0;
 +                      int needs_batch = 0;
 +                      int port_option = 'p';
                        char *ssh_host = hostandport;
                        const char *port = NULL;
                        transport_check_allowed("ssh");
                        }
  
                        ssh = get_ssh_command();
 -                      if (!ssh) {
 -                              const char *base;
 -                              char *ssh_dup;
 -
 +                      if (ssh)
 +                              handle_ssh_variant(ssh, 1, &port_option,
 +                                                 &needs_batch);
 +                      else {
                                /*
                                 * GIT_SSH is the no-shell version of
                                 * GIT_SSH_COMMAND (and must remain so for
                                ssh = getenv("GIT_SSH");
                                if (!ssh)
                                        ssh = "ssh";
 -
 -                              ssh_dup = xstrdup(ssh);
 -                              base = basename(ssh_dup);
 -
 -                              tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
 -                                      !strcasecmp(base, "tortoiseplink.exe");
 -                              putty = tortoiseplink ||
 -                                      !strcasecmp(base, "plink") ||
 -                                      !strcasecmp(base, "plink.exe");
 -
 -                              free(ssh_dup);
 +                              else
 +                                      handle_ssh_variant(ssh, 0,
 +                                                         &port_option,
 +                                                         &needs_batch);
                        }
  
                        argv_array_push(&conn->args, ssh);
                                argv_array_push(&conn->args, "-4");
                        else if (flags & CONNECT_IPV6)
                                argv_array_push(&conn->args, "-6");
 -                      if (tortoiseplink)
 +                      if (needs_batch)
                                argv_array_push(&conn->args, "-batch");
                        if (port) {
 -                              /* P is for PuTTY, p is for OpenSSH */
 -                              argv_array_push(&conn->args, putty ? "-P" : "-p");
 +                              argv_array_pushf(&conn->args,
 +                                               "-%c", port_option);
                                argv_array_push(&conn->args, port);
                        }
                        argv_array_push(&conn->args, ssh_host);