mirror of
https://github.com/git/git.git
synced 2026-01-26 10:35:18 +00:00
Merge branch 'coverity'
Coverity is a tool to analyze code statically, trying to find common (or not so common) problems before they occur in production. Coverity offers its services to Open Source software, and just like upstream Git, Git for Windows applied and was granted the use. While Coverity reports a lot of false positives due to Git's (ab-)use of the FLEX_ARRAY feature (where it declares a 0-byte or 1-byte array at the end of a struct, and then allocates a variable-length data structure holding a variable-length string at the end, so that the struct as well as the string can be released with a single free()), there were a few issues reported that are true positives, and not all of them were resource leaks in builtins (for which it is considered kind of okay to not release memory just before exit() is called anyway). This topic branch tries to address a couple of those issues. Note: there are a couple more issues left, either because they are tricky to resolve (in some cases, the custody of occasionally-allocated memory is very unclear) or because it is unclear whether they are false positives (due to the hard-to-reason-about nature of the code). It's a start, though. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
15
builtin/am.c
15
builtin/am.c
@@ -762,9 +762,11 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
|
||||
mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
|
||||
|
||||
out = fopen(mail, "w");
|
||||
if (!out)
|
||||
if (!out) {
|
||||
fclose(in);
|
||||
return error_errno(_("could not open '%s' for writing"),
|
||||
mail);
|
||||
}
|
||||
|
||||
ret = fn(out, in, keep_cr);
|
||||
|
||||
@@ -1355,15 +1357,16 @@ static int get_mail_commit_oid(struct object_id *commit_id, const char *mail)
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
FILE *fp = xfopen(mail, "r");
|
||||
const char *x;
|
||||
int ret = 0;
|
||||
|
||||
if (strbuf_getline_lf(&sb, fp))
|
||||
return -1;
|
||||
ret = -1;
|
||||
|
||||
if (!skip_prefix(sb.buf, "From ", &x))
|
||||
return -1;
|
||||
if (!ret && !skip_prefix(sb.buf, "From ", &x))
|
||||
ret = -1;
|
||||
|
||||
if (get_oid_hex(x, commit_id) < 0)
|
||||
return -1;
|
||||
if (!ret && get_oid_hex(x, commit_id) < 0)
|
||||
ret = -1;
|
||||
|
||||
strbuf_release(&sb);
|
||||
fclose(fp);
|
||||
|
||||
@@ -165,6 +165,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
||||
die("git cat-file %s: bad file", obj_name);
|
||||
|
||||
write_or_die(1, buf, size);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ static int checkout_merged(int pos, const struct checkout *state)
|
||||
if (!ce)
|
||||
die(_("make_cache_entry failed for path '%s'"), path);
|
||||
status = checkout_entry(ce, state, NULL);
|
||||
free(ce);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,7 @@ static void changed_files(struct hashmap *result, const char *index_path,
|
||||
hashmap_entry_init(entry, strhash(buf.buf));
|
||||
hashmap_add(result, entry);
|
||||
}
|
||||
fclose(fp);
|
||||
if (finish_command(&diff_files))
|
||||
die("diff-files did not exit properly");
|
||||
strbuf_release(&index_env);
|
||||
@@ -456,6 +457,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
if (finish_command(&child)) {
|
||||
ret = error("error occurred running diff --raw");
|
||||
goto finish;
|
||||
|
||||
@@ -765,6 +765,7 @@ static void handle_tag(const char *name, struct tag *tag)
|
||||
(int)(tagger_end - tagger), tagger,
|
||||
tagger == tagger_end ? "" : "\n",
|
||||
(int)message_size, (int)message_size, message ? message : "");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
|
||||
|
||||
@@ -232,7 +232,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
|
||||
|
||||
do {
|
||||
peek = fgetc(f);
|
||||
} while (isspace(peek));
|
||||
} while (peek >= 0 && isspace(peek));
|
||||
ungetc(peek, f);
|
||||
|
||||
if (strbuf_getwholeline(&buf, f, '\n')) {
|
||||
|
||||
@@ -72,7 +72,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
|
||||
unsigned mode;
|
||||
enum object_type mode_type; /* object type derived from mode */
|
||||
enum object_type obj_type; /* object type derived from sha */
|
||||
char *path;
|
||||
char *path, *p = NULL;
|
||||
unsigned char sha1[20];
|
||||
|
||||
ptr = buf;
|
||||
@@ -102,7 +102,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
|
||||
struct strbuf p_uq = STRBUF_INIT;
|
||||
if (unquote_c_style(&p_uq, path, NULL))
|
||||
die("invalid quoting");
|
||||
path = strbuf_detach(&p_uq, NULL);
|
||||
path = p = strbuf_detach(&p_uq, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -136,6 +136,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
|
||||
}
|
||||
|
||||
append_to_tree(mode, sha1, path);
|
||||
free(p);
|
||||
}
|
||||
|
||||
int cmd_mktree(int ac, const char **av, const char *prefix)
|
||||
|
||||
@@ -28,6 +28,7 @@ static void name_rev(struct commit *commit,
|
||||
struct rev_name *name = (struct rev_name *)commit->util;
|
||||
struct commit_list *parents;
|
||||
int parent_number = 1;
|
||||
char *p = NULL;
|
||||
|
||||
parse_commit(commit);
|
||||
|
||||
@@ -35,7 +36,7 @@ static void name_rev(struct commit *commit,
|
||||
return;
|
||||
|
||||
if (deref) {
|
||||
tip_name = xstrfmt("%s^0", tip_name);
|
||||
tip_name = p = xstrfmt("%s^0", tip_name);
|
||||
|
||||
if (generation)
|
||||
die("generation: %d, but deref?", generation);
|
||||
@@ -53,8 +54,10 @@ copy_data:
|
||||
name->taggerdate = taggerdate;
|
||||
name->generation = generation;
|
||||
name->distance = distance;
|
||||
} else
|
||||
} else {
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
for (parents = commit->parents;
|
||||
parents;
|
||||
|
||||
@@ -442,6 +442,7 @@ static void minimize(struct pack_list **min)
|
||||
/* return if there are no objects missing from the unique set */
|
||||
if (missing->size == 0) {
|
||||
*min = unique;
|
||||
free(missing);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -984,7 +984,8 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
{
|
||||
const char *name = cmd->ref_name;
|
||||
struct strbuf namespaced_name_buf = STRBUF_INIT;
|
||||
const char *namespaced_name, *ret;
|
||||
static char *namespaced_name;
|
||||
const char *ret;
|
||||
unsigned char *old_sha1 = cmd->old_sha1;
|
||||
unsigned char *new_sha1 = cmd->new_sha1;
|
||||
|
||||
@@ -995,6 +996,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
}
|
||||
|
||||
strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name);
|
||||
free(namespaced_name);
|
||||
namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);
|
||||
|
||||
if (is_ref_checked_out(namespaced_name)) {
|
||||
|
||||
@@ -408,9 +408,11 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
|
||||
find_unique_abbrev(wt->head_sha1, DEFAULT_ABBREV));
|
||||
if (wt->is_detached)
|
||||
strbuf_addstr(&sb, "(detached HEAD)");
|
||||
else if (wt->head_ref)
|
||||
strbuf_addf(&sb, "[%s]", shorten_unambiguous_ref(wt->head_ref, 0));
|
||||
else
|
||||
else if (wt->head_ref) {
|
||||
char *ref = shorten_unambiguous_ref(wt->head_ref, 0);
|
||||
strbuf_addf(&sb, "[%s]", ref);
|
||||
free(ref);
|
||||
} else
|
||||
strbuf_addstr(&sb, "(error)");
|
||||
}
|
||||
printf("%s\n", sb.buf);
|
||||
|
||||
@@ -1172,8 +1172,10 @@ static char **get_path_split(void)
|
||||
++n;
|
||||
}
|
||||
}
|
||||
if (!n)
|
||||
if (!n) {
|
||||
free(envpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ALLOC_ARRAY(path, n + 1);
|
||||
p = envpath;
|
||||
@@ -1566,12 +1568,18 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
|
||||
|
||||
if (getenv("GIT_STRACE_COMMANDS")) {
|
||||
char **path = get_path_split();
|
||||
cmd = path_lookup("strace.exe", path, 1);
|
||||
if (!cmd)
|
||||
char *p = path_lookup("strace.exe", path, 1);
|
||||
if (!p) {
|
||||
free_path_split(path);
|
||||
return error("strace not found!");
|
||||
if (xutftowcs_path(wcmd, cmd) < 0)
|
||||
}
|
||||
free_path_split(path);
|
||||
if (xutftowcs_path(wcmd, p) < 0) {
|
||||
free(p);
|
||||
return -1;
|
||||
}
|
||||
strbuf_insert(&args, 0, "strace ", 7);
|
||||
free(p);
|
||||
}
|
||||
|
||||
ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
|
||||
|
||||
@@ -100,6 +100,8 @@ static int is_console(int fd)
|
||||
if (!fd) {
|
||||
if (!GetConsoleMode(hcon, &mode))
|
||||
return 0;
|
||||
sbi.wAttributes = FOREGROUND_BLUE | FOREGROUND_GREEN |
|
||||
FOREGROUND_RED;
|
||||
} else if (!GetConsoleScreenBufferInfo(hcon, &sbi))
|
||||
return 0;
|
||||
|
||||
@@ -128,6 +130,11 @@ static void write_console(unsigned char *str, size_t len)
|
||||
|
||||
/* convert utf-8 to utf-16 */
|
||||
int wlen = xutftowcsn(wbuf, (char*) str, ARRAY_SIZE(wbuf), len);
|
||||
if (wlen < 0) {
|
||||
wchar_t *err = L"[invalid]";
|
||||
WriteConsoleW(console, err, wcslen(err), &dummy, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* write directly to console */
|
||||
WriteConsoleW(console, wbuf, wlen, &dummy, NULL);
|
||||
|
||||
5
config.c
5
config.c
@@ -2426,7 +2426,7 @@ int git_config_rename_section_in_file(const char *config_filename,
|
||||
struct lock_file *lock;
|
||||
int out_fd;
|
||||
char buf[1024];
|
||||
FILE *config_file;
|
||||
FILE *config_file = NULL;
|
||||
struct stat st;
|
||||
|
||||
if (new_name && !section_name_is_ok(new_name)) {
|
||||
@@ -2508,11 +2508,14 @@ int git_config_rename_section_in_file(const char *config_filename,
|
||||
}
|
||||
}
|
||||
fclose(config_file);
|
||||
config_file = NULL;
|
||||
commit_and_out:
|
||||
if (commit_lock_file(lock) < 0)
|
||||
ret = error_errno("could not write config file %s",
|
||||
config_filename);
|
||||
out:
|
||||
if (config_file)
|
||||
fclose(config_file);
|
||||
rollback_lock_file(lock);
|
||||
out_no_rollback:
|
||||
free(filename_buf);
|
||||
|
||||
@@ -716,8 +716,10 @@ static int handle_ssh_variant(const char *ssh_command, int is_cmdline,
|
||||
* any longer.
|
||||
*/
|
||||
free(ssh_argv);
|
||||
} else
|
||||
} else {
|
||||
free(ssh_argv);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(variant, "plink") ||
|
||||
|
||||
@@ -681,8 +681,10 @@ int cmd_main(int argc, const char **argv)
|
||||
if (!regexec(&re, dir, 1, out, 0)) {
|
||||
size_t n;
|
||||
|
||||
if (strcmp(method, c->method))
|
||||
if (strcmp(method, c->method)) {
|
||||
free(dir);
|
||||
return bad_request(&hdr, c);
|
||||
}
|
||||
|
||||
cmd = c;
|
||||
n = out[0].rm_eo - out[0].rm_so;
|
||||
@@ -708,5 +710,7 @@ int cmd_main(int argc, const char **argv)
|
||||
max_request_buffer);
|
||||
|
||||
cmd->imp(&hdr, cmd_arg);
|
||||
free(dir);
|
||||
free(cmd_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
5
ident.c
5
ident.c
@@ -169,9 +169,10 @@ const char *ident_default_email(void)
|
||||
strbuf_addstr(&git_default_email, email);
|
||||
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
||||
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
||||
} else if ((email = query_user_email()) && email[0])
|
||||
} else if ((email = query_user_email()) && email[0]) {
|
||||
strbuf_addstr(&git_default_email, email);
|
||||
else
|
||||
free((char *)email);
|
||||
} else
|
||||
copy_email(xgetpwuid_self(&default_email_is_bogus),
|
||||
&git_default_email, &default_email_is_bogus);
|
||||
strbuf_trim(&git_default_email);
|
||||
|
||||
@@ -1125,6 +1125,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
|
||||
changed = process_all_files(&parent_range, rev, &queue, range);
|
||||
if (parent)
|
||||
add_line_range(rev, parent, parent_range);
|
||||
free(parent_range);
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1094,7 +1094,7 @@ int mailinfo(struct mailinfo *mi, const char *msg, const char *patch)
|
||||
|
||||
do {
|
||||
peek = fgetc(mi->input);
|
||||
} while (isspace(peek));
|
||||
} while (peek >= 0 && isspace(peek));
|
||||
ungetc(peek, mi->input);
|
||||
|
||||
/* process the email header */
|
||||
|
||||
@@ -99,11 +99,12 @@ struct patch_id *has_commit_patch_id(struct commit *commit,
|
||||
struct patch_id *add_commit_patch_id(struct commit *commit,
|
||||
struct patch_ids *ids)
|
||||
{
|
||||
struct patch_id *key = xcalloc(1, sizeof(*key));
|
||||
struct patch_id *key;
|
||||
|
||||
if (!patch_id_defined(commit))
|
||||
return NULL;
|
||||
|
||||
key = xcalloc(1, sizeof(*key));
|
||||
if (init_patch_id_entry(key, commit, ids)) {
|
||||
free(key);
|
||||
return NULL;
|
||||
|
||||
@@ -183,7 +183,10 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
|
||||
if (!reflogs || reflogs->nr == 0) {
|
||||
unsigned char sha1[20];
|
||||
char *b;
|
||||
if (dwim_log(branch, strlen(branch), sha1, &b) == 1) {
|
||||
int ret = dwim_log(branch, strlen(branch), sha1, &b);
|
||||
if (ret > 1)
|
||||
free(b);
|
||||
else if (ret == 1) {
|
||||
if (reflogs) {
|
||||
free(reflogs->ref);
|
||||
free(reflogs);
|
||||
|
||||
5
remote.c
5
remote.c
@@ -1191,9 +1191,10 @@ static int match_explicit(struct ref *src, struct ref *dst,
|
||||
else if (is_null_oid(&matched_src->new_oid))
|
||||
error("unable to delete '%s': remote ref does not exist",
|
||||
dst_value);
|
||||
else if ((dst_guess = guess_ref(dst_value, matched_src)))
|
||||
else if ((dst_guess = guess_ref(dst_value, matched_src))) {
|
||||
matched_dst = make_linked_ref(dst_guess, dst_tail);
|
||||
else
|
||||
free(dst_guess);
|
||||
} else
|
||||
error("unable to push to unqualified destination: %s\n"
|
||||
"The destination refspec neither matches an "
|
||||
"existing ref on the remote nor\n"
|
||||
|
||||
@@ -2678,11 +2678,13 @@ int skip_unnecessary_picks(void)
|
||||
if (write_in_full(fd, todo_list.buf.buf + offset,
|
||||
todo_list.buf.len - offset) < 0) {
|
||||
todo_list_release(&todo_list);
|
||||
close(fd);
|
||||
return error_errno(_("could not write to '%s'"),
|
||||
rebase_path_todo());
|
||||
}
|
||||
if (ftruncate(fd, todo_list.buf.len - offset) < 0) {
|
||||
todo_list_release(&todo_list);
|
||||
close(fd);
|
||||
return error_errno(_("could not truncate '%s'"),
|
||||
rebase_path_todo());
|
||||
}
|
||||
|
||||
11
setup.c
11
setup.c
@@ -697,11 +697,16 @@ static const char *setup_discovered_git_dir(const char *gitdir,
|
||||
|
||||
/* --work-tree is set without --git-dir; use discovered one */
|
||||
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
|
||||
char *p = NULL;
|
||||
const char *ret;
|
||||
|
||||
if (offset != cwd->len && !is_absolute_path(gitdir))
|
||||
gitdir = real_pathdup(gitdir, 1);
|
||||
gitdir = p = real_pathdup(gitdir, 1);
|
||||
if (chdir(cwd->buf))
|
||||
die_errno("Could not come back to cwd");
|
||||
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
|
||||
ret = setup_explicit_git_dir(gitdir, cwd, nongit_ok);
|
||||
free(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
|
||||
@@ -740,7 +745,7 @@ static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
|
||||
|
||||
/* --work-tree is set without --git-dir; use discovered one */
|
||||
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
|
||||
const char *gitdir;
|
||||
static const char *gitdir;
|
||||
|
||||
gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
|
||||
if (chdir(cwd->buf))
|
||||
|
||||
@@ -473,11 +473,15 @@ static void paint_down(struct paint_info *info, const unsigned char *sha1,
|
||||
struct commit_list *head = NULL;
|
||||
int bitmap_nr = (info->nr_bits + 31) / 32;
|
||||
size_t bitmap_size = st_mult(sizeof(uint32_t), bitmap_nr);
|
||||
uint32_t *tmp = xmalloc(bitmap_size); /* to be freed before return */
|
||||
uint32_t *bitmap = paint_alloc(info);
|
||||
struct commit *c = lookup_commit_reference_gently(sha1, 1);
|
||||
uint32_t *tmp; /* to be freed before return */
|
||||
uint32_t *bitmap;
|
||||
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
tmp = xmalloc(bitmap_size);
|
||||
bitmap = paint_alloc(info);
|
||||
memset(bitmap, 0, bitmap_size);
|
||||
bitmap[id / 32] |= (1U << (id % 32));
|
||||
commit_list_insert(c, &head);
|
||||
|
||||
@@ -396,6 +396,7 @@ int submodule_uses_worktrees(const char *path)
|
||||
|
||||
/* The env would be set for the superproject. */
|
||||
get_common_dir_noenv(&sb, submodule_gitdir);
|
||||
free(submodule_gitdir);
|
||||
|
||||
/*
|
||||
* The check below is only known to be good for repository format
|
||||
@@ -415,7 +416,6 @@ int submodule_uses_worktrees(const char *path)
|
||||
/* See if there is any file inside the worktrees directory. */
|
||||
dir = opendir(sb.buf);
|
||||
strbuf_release(&sb);
|
||||
free(submodule_gitdir);
|
||||
|
||||
if (!dir)
|
||||
return 0;
|
||||
|
||||
@@ -1075,8 +1075,13 @@ static int split_commit_in_progress(struct wt_status *s)
|
||||
char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
|
||||
|
||||
if (!head || !orig_head || !rebase_amend || !rebase_orig_head ||
|
||||
!s->branch || strcmp(s->branch, "HEAD"))
|
||||
!s->branch || strcmp(s->branch, "HEAD")) {
|
||||
free(head);
|
||||
free(orig_head);
|
||||
free(rebase_amend);
|
||||
free(rebase_orig_head);
|
||||
return split_in_progress;
|
||||
}
|
||||
|
||||
if (!strcmp(rebase_amend, rebase_orig_head)) {
|
||||
if (strcmp(head, rebase_amend))
|
||||
@@ -1155,6 +1160,7 @@ static int read_rebase_todolist(const char *fname, struct string_list *lines)
|
||||
abbrev_sha1_in_line(&line);
|
||||
string_list_append(lines, line.buf);
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user