Merge branch 'jk/misc-fixes-maint'
authorJunio C Hamano <gitster@pobox.com>
Mon, 28 Jul 2014 18:30:41 +0000 (11:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 28 Jul 2014 18:30:41 +0000 (11:30 -0700)
* jk/misc-fixes-maint:
apply: avoid possible bogus pointer
fix memory leak parsing core.commentchar
transport: fix leaks in refs_from_alternate_cb
free ref string returned by dwim_ref
receive-pack: don't copy "dir" parameter

1  2 
builtin/apply.c
builtin/receive-pack.c
builtin/rev-parse.c
builtin/show-branch.c
config.c
sha1_name.c
transport.c
diff --combined builtin/apply.c
index 9f8f5bac072661adf9b911b091ab4202796e9a9e,5b7a3066adca5912b2ac2551a89f74531decb9aa..be2b4ce2fd91640379b0a65d0aa90238d7edfd64
@@@ -300,13 -300,11 +300,13 @@@ static int fuzzy_matchlines(const char 
        while ((*last2 == '\r') || (*last2 == '\n'))
                last2--;
  
 -      /* skip leading whitespace */
 -      while (isspace(*s1) && (s1 <= last1))
 -              s1++;
 -      while (isspace(*s2) && (s2 <= last2))
 -              s2++;
 +      /* skip leading whitespaces, if both begin with whitespace */
 +      if (s1 <= last1 && s2 <= last2 && isspace(*s1) && isspace(*s2)) {
 +              while (isspace(*s1) && (s1 <= last1))
 +                      s1++;
 +              while (isspace(*s2) && (s2 <= last2))
 +                      s2++;
 +      }
        /* early return if both lines are empty */
        if ((s1 > last1) && (s2 > last2))
                return 1;
@@@ -1075,7 -1073,7 +1075,7 @@@ static int gitdiff_index(const char *li
  
        line = ptr + 2;
        ptr = strchr(line, ' ');
-       eol = strchr(line, '\n');
+       eol = strchrnul(line, '\n');
  
        if (!ptr || eol < ptr)
                ptr = eol;
@@@ -1281,7 -1279,9 +1281,7 @@@ static int parse_git_header(const char 
         */
        patch->def_name = git_header_name(line, len);
        if (patch->def_name && root) {
 -              char *s = xmalloc(root_len + strlen(patch->def_name) + 1);
 -              strcpy(s, root);
 -              strcpy(s + root_len, patch->def_name);
 +              char *s = xstrfmt("%s%s", root, patch->def_name);
                free(patch->def_name);
                patch->def_name = s;
        }
@@@ -2867,7 -2867,9 +2867,7 @@@ static int apply_binary_fragment(struc
        case BINARY_LITERAL_DEFLATED:
                clear_image(img);
                img->len = fragment->size;
 -              img->buf = xmalloc(img->len+1);
 -              memcpy(img->buf, fragment->patch, img->len);
 -              img->buf[img->len] = '\0';
 +              img->buf = xmemdupz(fragment->patch, img->len);
                return 0;
        }
        return -1;
@@@ -3082,15 -3084,13 +3082,15 @@@ static void prepare_fn_table(struct pat
        }
  }
  
 -static int checkout_target(struct cache_entry *ce, struct stat *st)
 +static int checkout_target(struct index_state *istate,
 +                         struct cache_entry *ce, struct stat *st)
  {
        struct checkout costate;
  
        memset(&costate, 0, sizeof(costate));
        costate.base_dir = "";
        costate.refresh_cache = 1;
 +      costate.istate = istate;
        if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st))
                return error(_("cannot checkout %s"), ce->name);
        return 0;
@@@ -3257,7 -3257,7 +3257,7 @@@ static int load_current(struct image *i
        if (lstat(name, &st)) {
                if (errno != ENOENT)
                        return error(_("%s: %s"), name, strerror(errno));
 -              if (checkout_target(ce, &st))
 +              if (checkout_target(&the_index, ce, &st))
                        return -1;
        }
        if (verify_index_match(ce, &st))
@@@ -3411,7 -3411,7 +3411,7 @@@ static int check_preimage(struct patch 
                }
                *ce = active_cache[pos];
                if (stat_ret < 0) {
 -                      if (checkout_target(*ce, st))
 +                      if (checkout_target(&the_index, *ce, st))
                                return -1;
                }
                if (!cached && verify_index_match(*ce, st))
@@@ -3644,7 -3644,7 +3644,7 @@@ static void build_fake_ancestor(struct 
  {
        struct patch *patch;
        struct index_state result = { NULL };
 -      int fd;
 +      static struct lock_file lock;
  
        /* Once we start supporting the reverse patch, it may be
         * worth showing the new sha1 prefix, but until then...
                        die ("Could not add %s to temporary index", name);
        }
  
 -      fd = open(filename, O_WRONLY | O_CREAT, 0666);
 -      if (fd < 0 || write_index(&result, fd) || close(fd))
 +      hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
 +      if (write_locked_index(&result, &lock, COMMIT_LOCK))
                die ("Could not write temporary index to %s", filename);
  
        discard_index(&result);
@@@ -3845,10 -3845,9 +3845,10 @@@ static void add_index_file(const char *
        ce->ce_flags = create_ce_flags(0);
        ce->ce_namelen = namelen;
        if (S_ISGITLINK(mode)) {
 -              const char *s = buf;
 +              const char *s;
  
 -              if (get_sha1_hex(s + strlen("Subproject commit "), ce->sha1))
 +              if (!skip_prefix(buf, "Subproject commit ", &s) ||
 +                  get_sha1_hex(s, ce->sha1))
                        die(_("corrupt patch for submodule %s"), path);
        } else {
                if (!cached) {
@@@ -4502,7 -4501,8 +4502,7 @@@ int cmd_apply(int argc, const char **ar
        }
  
        if (update_index) {
 -              if (write_cache(newfd, active_cache, active_nr) ||
 -                  commit_locked_index(&lock_file))
 +              if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
                        die(_("Unable to write new index file"));
        }
  
diff --combined builtin/receive-pack.c
index 92561bffc1ea4ba11d3fd45aa3e216edda3461f7,be8c2db26cde55df967d9a1ba6ea02ea08024ffc..f93ac454b4133f5c1e7cb1675a618b4c0b3174cd
@@@ -438,7 -438,7 +438,7 @@@ static int update_shallow_ref(struct co
        uint32_t mask = 1 << (cmd->index % 32);
        int i;
  
 -      trace_printf_key("GIT_TRACE_SHALLOW",
 +      trace_printf_key(&trace_shallow,
                         "shallow: update_shallow_ref %s\n", cmd->ref_name);
        for (i = 0; i < si->shallow->nr; i++)
                if (si->used_shallow[i] &&
@@@ -614,9 -614,12 +614,9 @@@ static void run_update_post_hook(struc
        argv[0] = hook;
  
        for (argc = 1, cmd = commands; cmd; cmd = cmd->next) {
 -              char *p;
                if (cmd->error_string || cmd->did_not_exist)
                        continue;
 -              p = xmalloc(strlen(cmd->ref_name) + 1);
 -              strcpy(p, cmd->ref_name);
 -              argv[argc] = p;
 +              argv[argc] = xstrdup(cmd->ref_name);
                argc++;
        }
        argv[argc] = NULL;
@@@ -1122,7 -1125,7 +1122,7 @@@ int cmd_receive_pack(int argc, const ch
        int advertise_refs = 0;
        int stateless_rpc = 0;
        int i;
-       char *dir = NULL;
+       const char *dir = NULL;
        struct command *commands;
        struct sha1_array shallow = SHA1_ARRAY_INIT;
        struct sha1_array ref = SHA1_ARRAY_INIT;
                }
                if (dir)
                        usage(receive_pack_usage);
-               dir = xstrdup(arg);
+               dir = arg;
        }
        if (!dir)
                usage(receive_pack_usage);
diff --combined builtin/rev-parse.c
index 8102aaa9248d55055761f9899903cac2a2c7cc1e,0bce2a63d44028385db60c69793b9a6bbf4634cd..d85e08cc9cc22ee307470dbeb12fdd8d1eea655b
@@@ -11,7 -11,6 +11,7 @@@
  #include "parse-options.h"
  #include "diff.h"
  #include "revision.h"
 +#include "split-index.h"
  
  #define DO_REVS               1
  #define DO_NOREV      2
@@@ -151,6 -150,7 +151,7 @@@ static void show_rev(int type, const un
                                error("refname '%s' is ambiguous", name);
                                break;
                        }
+                       free(full);
                } else {
                        show_with_type(type, name);
                }
@@@ -776,15 -776,6 +777,15 @@@ int cmd_rev_parse(int argc, const char 
                                                : "false");
                                continue;
                        }
 +                      if (!strcmp(arg, "--shared-index-path")) {
 +                              if (read_cache() < 0)
 +                                      die(_("Could not read the index"));
 +                              if (the_index.split_index) {
 +                                      const unsigned char *sha1 = the_index.split_index->base_sha1;
 +                                      puts(git_path("sharedindex.%s", sha1_to_hex(sha1)));
 +                              }
 +                              continue;
 +                      }
                        if (starts_with(arg, "--since=")) {
                                show_datestring("--max-age=", arg+8);
                                continue;
diff --combined builtin/show-branch.c
index 5fd4e4e48839a9dc2998d3fba0e48008b902b12a,b29309019bd3e332b3db458aa14f341bd0c82f58..298c95e3f8b03e7f89d7767407ca8cee3eecc591
@@@ -755,7 -755,7 +755,7 @@@ int cmd_show_branch(int ac, const char 
                }
  
                for (i = 0; i < reflog; i++) {
 -                      char *logmsg, *m;
 +                      char *logmsg;
                        const char *msg;
                        unsigned long timestamp;
                        int tz;
                                msg = "(none)";
                        else
                                msg++;
 -                      m = xmalloc(strlen(msg) + 200);
 -                      sprintf(m, "(%s) %s",
 -                              show_date(timestamp, tz, 1),
 -                              msg);
 -                      reflog_msg[i] = m;
 +                      reflog_msg[i] = xstrfmt("(%s) %s",
 +                                              show_date(timestamp, tz, 1),
 +                                              msg);
                        free(logmsg);
                        sprintf(nth_desc, "%s@{%d}", *av, base+i);
                        append_ref(nth_desc, sha1, 1);
                }
+               free(ref);
        }
        else if (all_heads + all_remotes)
                snarf_refs(all_heads, all_remotes);
diff --combined config.c
index 9767c4bad0d0ae4af58a5f1e7f14d124d1174e10,40799a1dbaa1a156a5d2693e1e17eb85d52e3a0e..058505cb8d8d8bb531527b620125b0204732458a
+++ b/config.c
@@@ -138,7 -138,8 +138,7 @@@ int git_config_include(const char *var
        if (ret < 0)
                return ret;
  
 -      type = skip_prefix(var, "include.");
 -      if (!type)
 +      if (!skip_prefix(var, "include.", &type))
                return ret;
  
        if (!strcmp(type, "path"))
        return ret;
  }
  
 -static void lowercase(char *p)
 -{
 -      for (; *p; p++)
 -              *p = tolower(*p);
 -}
 -
  void git_config_push_parameter(const char *text)
  {
        struct strbuf env = STRBUF_INIT;
@@@ -173,7 -180,7 +173,7 @@@ int git_config_parse_parameter(const ch
                strbuf_list_free(pair);
                return error("bogus config parameter: %s", text);
        }
 -      lowercase(pair[0]->buf);
 +      strbuf_tolower(pair[0]);
        if (fn(pair[0]->buf, pair[1] ? pair[1]->buf : NULL, data) < 0) {
                strbuf_list_free(pair);
                return -1;
@@@ -817,17 -824,10 +817,15 @@@ static int git_default_core_config(cons
                return git_config_string(&editor_program, var, value);
  
        if (!strcmp(var, "core.commentchar")) {
-               const char *comment;
-               int ret = git_config_string(&comment, var, value);
-               if (ret)
-                       return ret;
-               else if (!strcasecmp(comment, "auto"))
+               if (!value)
+                       return config_error_nonbool(var);
 -              else
++              else if (!strcasecmp(value, "auto"))
 +                      auto_comment_line_char = 1;
-               else if (comment[0] && !comment[1]) {
-                       comment_line_char = comment[0];
++              else if (value[0] && !value[1]) {
+                       comment_line_char = value[0];
 +                      auto_comment_line_char = 0;
 +              } else
 +                      return error("core.commentChar should only be one character");
                return 0;
        }
  
@@@ -952,7 -952,7 +950,7 @@@ static int git_default_push_config(cons
  static int git_default_mailmap_config(const char *var, const char *value)
  {
        if (!strcmp(var, "mailmap.file"))
 -              return git_config_string(&git_mailmap_file, var, value);
 +              return git_config_pathname(&git_mailmap_file, var, value);
        if (!strcmp(var, "mailmap.blob"))
                return git_config_string(&git_mailmap_blob, var, value);
  
@@@ -1538,7 -1538,7 +1536,7 @@@ int git_config_set_multivar_in_file(con
         * The lock serves a purpose in addition to locking: the new
         * contents of .git/config will be written into it.
         */
 -      lock = xcalloc(sizeof(struct lock_file), 1);
 +      lock = xcalloc(1, sizeof(struct lock_file));
        fd = hold_lock_file_for_update(lock, config_filename, 0);
        if (fd < 0) {
                error("could not lock config file %s: %s", config_filename, strerror(errno));
                        MAP_PRIVATE, in_fd, 0);
                close(in_fd);
  
 +              if (chmod(lock->filename, st.st_mode & 07777) < 0) {
 +                      error("chmod on %s failed: %s",
 +                              lock->filename, strerror(errno));
 +                      ret = CONFIG_NO_WRITE;
 +                      goto out_free;
 +              }
 +
                if (store.seen == 0)
                        store.seen = 1;
  
@@@ -1791,7 -1784,6 +1789,7 @@@ int git_config_rename_section_in_file(c
        int out_fd;
        char buf[1024];
        FILE *config_file;
 +      struct stat st;
  
        if (new_name && !section_name_is_ok(new_name)) {
                ret = error("invalid section name: %s", new_name);
        if (!config_filename)
                config_filename = filename_buf = git_pathdup("config");
  
 -      lock = xcalloc(sizeof(struct lock_file), 1);
 +      lock = xcalloc(1, sizeof(struct lock_file));
        out_fd = hold_lock_file_for_update(lock, config_filename, 0);
        if (out_fd < 0) {
                ret = error("could not lock config file %s", config_filename);
                goto unlock_and_out;
        }
  
 +      fstat(fileno(config_file), &st);
 +
 +      if (chmod(lock->filename, st.st_mode & 07777) < 0) {
 +              ret = error("chmod on %s failed: %s",
 +                              lock->filename, strerror(errno));
 +              goto out;
 +      }
 +
        while (fgets(buf, sizeof(buf), config_file)) {
                int i;
                int length;
diff --combined sha1_name.c
index 6ccd3a53f8fc6130000c4bf3ba4cd646f512de53,cc3941eb084863045e3af5de78d685465c26102d..63ee66fedd617e2cacfae7a763f43ee600d15273
@@@ -540,8 -540,10 +540,10 @@@ static int get_sha1_basic(const char *s
                        char *tmp = xstrndup(str + at + 2, reflog_len);
                        at_time = approxidate_careful(tmp, &errors);
                        free(tmp);
-                       if (errors)
+                       if (errors) {
+                               free(real_ref);
                                return -1;
+                       }
                }
                if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
                                &co_time, &co_tz, &co_cnt)) {
@@@ -862,17 -864,27 +864,17 @@@ static int get_sha1_oneline(const char 
                commit_list_insert(l->item, &backup);
        }
        while (list) {
 -              char *p, *to_free = NULL;
 +              const char *p, *buf;
                struct commit *commit;
 -              enum object_type type;
 -              unsigned long size;
                int matches;
  
                commit = pop_most_recent_commit(&list, ONELINE_SEEN);
                if (!parse_object(commit->object.sha1))
                        continue;
 -              if (commit->buffer)
 -                      p = commit->buffer;
 -              else {
 -                      p = read_sha1_file(commit->object.sha1, &type, &size);
 -                      if (!p)
 -                              continue;
 -                      to_free = p;
 -              }
 -
 -              p = strstr(p, "\n\n");
 +              buf = get_commit_buffer(commit, NULL);
 +              p = strstr(buf, "\n\n");
                matches = p && !regexec(&regex, p + 2, 0, NULL, 0);
 -              free(to_free);
 +              unuse_commit_buffer(commit, buf);
  
                if (matches) {
                        hashcpy(sha1, commit->object.sha1);
@@@ -901,8 -913,10 +903,8 @@@ static int grab_nth_branch_switch(unsig
        const char *match = NULL, *target = NULL;
        size_t len;
  
 -      if (starts_with(message, "checkout: moving from ")) {
 -              match = message + strlen("checkout: moving from ");
 +      if (skip_prefix(message, "checkout: moving from ", &match))
                target = strstr(match, " to ");
 -      }
  
        if (!match || !target)
                return 0;
@@@ -946,7 -960,7 +948,7 @@@ static int interpret_nth_prior_checkout
        retval = 0;
        if (0 < for_each_reflog_ent_reverse("HEAD", grab_nth_branch_switch, &cb)) {
                strbuf_reset(buf);
 -              strbuf_add(buf, cb.buf.buf, cb.buf.len);
 +              strbuf_addbuf(buf, &cb.buf);
                retval = brace - name + 1;
        }
  
@@@ -1240,7 -1254,10 +1242,7 @@@ static void diagnose_invalid_sha1_path(
                die("Path '%s' exists on disk, but not in '%.*s'.",
                    filename, object_name_len, object_name);
        if (errno == ENOENT || errno == ENOTDIR) {
 -              char *fullname = xmalloc(strlen(filename)
 -                                           + strlen(prefix) + 1);
 -              strcpy(fullname, prefix);
 -              strcat(fullname, filename);
 +              char *fullname = xstrfmt("%s%s", prefix, filename);
  
                if (!get_tree_entry(tree_sha1, fullname,
                                    sha1, &mode)) {
diff --combined transport.c
index 80ed1262c29e8e3ec1443e06383c4ee9b7d14173,e735633a6198a89927403fd832c4fb8a5f486abc..662421bb5e076177f0fc320330287d3da50303a5
@@@ -192,9 -192,7 +192,9 @@@ static void set_upstreams(struct transp
  
  static const char *rsync_url(const char *url)
  {
 -      return !starts_with(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
 +      if (!starts_with(url, "rsync://"))
 +              skip_prefix(url, "rsync:", &url);
 +      return url;
  }
  
  static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
  static int fetch_objs_via_rsync(struct transport *transport,
                                int nr_objs, struct ref **to_fetch)
  {
 -      struct strbuf buf = STRBUF_INIT;
        struct child_process rsync;
 -      const char *args[8];
 -      int result;
 -
 -      strbuf_addstr(&buf, rsync_url(transport->url));
 -      strbuf_addstr(&buf, "/objects/");
  
        memset(&rsync, 0, sizeof(rsync));
 -      rsync.argv = args;
        rsync.stdout_to_stderr = 1;
 -      args[0] = "rsync";
 -      args[1] = (transport->verbose > 1) ? "-rv" : "-r";
 -      args[2] = "--ignore-existing";
 -      args[3] = "--exclude";
 -      args[4] = "info";
 -      args[5] = buf.buf;
 -      args[6] = get_object_directory();
 -      args[7] = NULL;
 +      argv_array_push(&rsync.args, "rsync");
 +      argv_array_push(&rsync.args, (transport->verbose > 1) ? "-rv" : "-r");
 +      argv_array_push(&rsync.args, "--ignore-existing");
 +      argv_array_push(&rsync.args, "--exclude");
 +      argv_array_push(&rsync.args, "info");
 +      argv_array_pushf(&rsync.args, "%s/objects/", rsync_url(transport->url));
 +      argv_array_push(&rsync.args, get_object_directory());
  
        /* NEEDSWORK: handle one level of alternates */
 -      result = run_command(&rsync);
 -
 -      strbuf_release(&buf);
 -
 -      return result;
 +      return run_command(&rsync);
  }
  
  static int write_one_ref(const char *name, const unsigned char *sha1,
@@@ -1176,8 -1186,10 +1176,8 @@@ int transport_push(struct transport *tr
                if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
                              TRANSPORT_RECURSE_SUBMODULES_CHECK)) && !is_bare_repository()) {
                        struct ref *ref = remote_refs;
 -                      struct string_list needs_pushing;
 +                      struct string_list needs_pushing = STRING_LIST_INIT_DUP;
  
 -                      memset(&needs_pushing, 0, sizeof(struct string_list));
 -                      needs_pushing.strdup_strings = 1;
                        for (; ref; ref = ref->next)
                                if (!is_null_sha1(ref->new_sha1) &&
                                    find_unpushed_submodules(ref->new_sha1,
@@@ -1357,11 -1369,11 +1357,11 @@@ static int refs_from_alternate_cb(struc
        while (other[len-1] == '/')
                other[--len] = '\0';
        if (len < 8 || memcmp(other + len - 8, "/objects", 8))
-               return 0;
+               goto out;
        /* Is this a git repository with refs? */
        memcpy(other + len - 8, "/refs", 6);
        if (!is_directory(other))
-               return 0;
+               goto out;
        other[len - 8] = '\0';
        remote = remote_get(other);
        transport = transport_get(remote, other);
             extra = extra->next)
                cb->fn(extra, cb->data);
        transport_disconnect(transport);
+ out:
        free(other);
        return 0;
  }