Merge branch 'js/plug-leaks' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 4 Jun 2017 01:21:04 +0000 (10:21 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sun, 4 Jun 2017 01:21:04 +0000 (10:21 +0900)
Fix memory leaks pointed out by Coverity (and people).

* js/plug-leaks: (26 commits)
checkout: fix memory leak
submodule_uses_worktrees(): plug memory leak
show_worktree(): plug memory leak
name-rev: avoid leaking memory in the `deref` case
remote: plug memory leak in match_explicit()
add_reflog_for_walk: avoid memory leak
shallow: avoid memory leak
line-log: avoid memory leak
receive-pack: plug memory leak in update()
fast-export: avoid leaking memory in handle_tag()
mktree: plug memory leaks reported by Coverity
pack-redundant: plug memory leak
setup_discovered_git_dir(): plug memory leak
setup_bare_git_dir(): help static analysis
split_commit_in_progress(): simplify & fix memory leak
checkout: fix memory leak
cat-file: fix memory leak
mailinfo & mailsplit: check for EOF while parsing
status: close file descriptor after reading git-rebase-todo
difftool: address a couple of resource/memory leaks
...

1  2 
builtin/am.c
builtin/checkout.c
diff --combined builtin/am.c
index 7d39156ff3f8230c2898439dfa38aeca46b6e4d0,9c5c2c778e28dc5bc2bfc3e5a1cf32c247ed273f..4b89289d1e7dae8073279cc115dafc6b2cf183a4
@@@ -1312,7 -1312,7 +1312,7 @@@ static int parse_mail(struct am_state *
        }
  
        if (is_empty_file(am_path(state, "patch"))) {
 -              printf_ln(_("Patch is empty. Was it split wrong?"));
 +              printf_ln(_("Patch is empty."));
                die_user_resolve(state);
        }
  
@@@ -1351,19 -1351,16 +1351,16 @@@ static int get_mail_commit_oid(struct o
        struct strbuf sb = STRBUF_INIT;
        FILE *fp = xfopen(mail, "r");
        const char *x;
+       int ret = 0;
  
-       if (strbuf_getline_lf(&sb, fp))
-               return -1;
-       if (!skip_prefix(sb.buf, "From ", &x))
-               return -1;
-       if (get_oid_hex(x, commit_id) < 0)
-               return -1;
+       if (strbuf_getline_lf(&sb, fp) ||
+           !skip_prefix(sb.buf, "From ", &x) ||
+           get_oid_hex(x, commit_id) < 0)
+               ret = -1;
  
        strbuf_release(&sb);
        fclose(fp);
-       return 0;
+       return ret;
  }
  
  /**
   */
  static void get_commit_info(struct am_state *state, struct commit *commit)
  {
 -      const char *buffer, *ident_line, *author_date, *msg;
 +      const char *buffer, *ident_line, *msg;
        size_t ident_len;
 -      struct ident_split ident_split;
 -      struct strbuf sb = STRBUF_INIT;
 +      struct ident_split id;
  
        buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding());
  
        ident_line = find_commit_header(buffer, "author", &ident_len);
  
 -      if (split_ident_line(&ident_split, ident_line, ident_len) < 0) {
 -              strbuf_add(&sb, ident_line, ident_len);
 -              die(_("invalid ident line: %s"), sb.buf);
 -      }
 +      if (split_ident_line(&id, ident_line, ident_len) < 0)
 +              die(_("invalid ident line: %.*s"), (int)ident_len, ident_line);
  
        assert(!state->author_name);
 -      if (ident_split.name_begin) {
 -              strbuf_add(&sb, ident_split.name_begin,
 -                      ident_split.name_end - ident_split.name_begin);
 -              state->author_name = strbuf_detach(&sb, NULL);
 -      } else
 +      if (id.name_begin)
 +              state->author_name =
 +                      xmemdupz(id.name_begin, id.name_end - id.name_begin);
 +      else
                state->author_name = xstrdup("");
  
        assert(!state->author_email);
 -      if (ident_split.mail_begin) {
 -              strbuf_add(&sb, ident_split.mail_begin,
 -                      ident_split.mail_end - ident_split.mail_begin);
 -              state->author_email = strbuf_detach(&sb, NULL);
 -      } else
 +      if (id.mail_begin)
 +              state->author_email =
 +                      xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
 +      else
                state->author_email = xstrdup("");
  
 -      author_date = show_ident_date(&ident_split, DATE_MODE(NORMAL));
 -      strbuf_addstr(&sb, author_date);
        assert(!state->author_date);
 -      state->author_date = strbuf_detach(&sb, NULL);
 +      state->author_date = xstrdup(show_ident_date(&id, DATE_MODE(NORMAL)));
  
        assert(!state->msg);
        msg = strstr(buffer, "\n\n");
                die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid));
        state->msg = xstrdup(msg + 2);
        state->msg_len = strlen(state->msg);
 +      unuse_commit_buffer(commit, buffer);
  }
  
  /**
@@@ -1934,8 -1937,7 +1931,8 @@@ static void am_resolve(struct am_state 
  
        if (unmerged_cache()) {
                printf_ln(_("You still have unmerged paths in your index.\n"
 -                      "Did you forget to use 'git add'?"));
 +                      "You should 'git add' each file with resolved conflicts to mark them as such.\n"
 +                      "You might run `git rm` on a file to accept \"deleted by them\" for it."));
                die_user_resolve(state);
        }
  
diff --combined builtin/checkout.c
index 85c04d252ce9b7c6d608b3c989783d1b8d9f85ec,94849cf250ebcf35efe17c120205359d91ae7648..e079a7dc83b32c781f63fe1a7721c54182894910
@@@ -235,22 -235,24 +235,24 @@@ static int checkout_merged(int pos, con
        /*
         * NEEDSWORK:
         * There is absolutely no reason to write this as a blob object
-        * and create a phony cache entry just to leak.  This hack is
-        * primarily to get to the write_entry() machinery that massages
-        * the contents to work-tree format and writes out which only
-        * allows it for a cache entry.  The code in write_entry() needs
-        * to be refactored to allow us to feed a <buffer, size, mode>
-        * instead of a cache entry.  Such a refactoring would help
-        * merge_recursive as well (it also writes the merge result to the
-        * object database even when it may contain conflicts).
+        * and create a phony cache entry.  This hack is primarily to get
+        * to the write_entry() machinery that massages the contents to
+        * work-tree format and writes out which only allows it for a
+        * cache entry.  The code in write_entry() needs to be refactored
+        * to allow us to feed a <buffer, size, mode> instead of a cache
+        * entry.  Such a refactoring would help merge_recursive as well
+        * (it also writes the merge result to the object database even
+        * when it may contain conflicts).
         */
        if (write_sha1_file(result_buf.ptr, result_buf.size,
                            blob_type, oid.hash))
                die(_("Unable to add merge result for '%s'"), path);
+       free(result_buf.ptr);
        ce = make_cache_entry(mode, oid.hash, path, 2, 0);
        if (!ce)
                die(_("make_cache_entry failed for path '%s'"), path);
        status = checkout_entry(ce, state, NULL);
+       free(ce);
        return status;
  }
  
@@@ -1286,8 -1288,9 +1288,8 @@@ int cmd_checkout(int argc, const char *
                 * new_branch && argc > 1 will be caught later.
                 */
                if (opts.new_branch && argc == 1)
 -                      die(_("Cannot update paths and switch to branch '%s' at the same time.\n"
 -                            "Did you intend to checkout '%s' which can not be resolved as commit?"),
 -                          opts.new_branch, argv[0]);
 +                      die(_("'%s' is not a commit and a branch '%s' cannot be created from it"),
 +                              argv[0], opts.new_branch);
  
                if (opts.force_detach)
                        die(_("git checkout: --detach does not take a path argument '%s'"),