Skip to content

Commit bf1cd08

Browse files
committed
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 <[email protected]>
2 parents 37dabec + f07be76 commit bf1cd08

27 files changed

+101
-36
lines changed

builtin/am.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -762,9 +762,11 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
762762
mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
763763

764764
out = fopen(mail, "w");
765-
if (!out)
765+
if (!out) {
766+
fclose(in);
766767
return error_errno(_("could not open '%s' for writing"),
767768
mail);
769+
}
768770

769771
ret = fn(out, in, keep_cr);
770772

@@ -1355,15 +1357,16 @@ static int get_mail_commit_oid(struct object_id *commit_id, const char *mail)
13551357
struct strbuf sb = STRBUF_INIT;
13561358
FILE *fp = xfopen(mail, "r");
13571359
const char *x;
1360+
int ret = 0;
13581361

13591362
if (strbuf_getline_lf(&sb, fp))
1360-
return -1;
1363+
ret = -1;
13611364

1362-
if (!skip_prefix(sb.buf, "From ", &x))
1363-
return -1;
1365+
if (!ret && !skip_prefix(sb.buf, "From ", &x))
1366+
ret = -1;
13641367

1365-
if (get_oid_hex(x, commit_id) < 0)
1366-
return -1;
1368+
if (!ret && get_oid_hex(x, commit_id) < 0)
1369+
ret = -1;
13671370

13681371
strbuf_release(&sb);
13691372
fclose(fp);

builtin/cat-file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
165165
die("git cat-file %s: bad file", obj_name);
166166

167167
write_or_die(1, buf, size);
168+
free(buf);
168169
return 0;
169170
}
170171

builtin/checkout.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ static int checkout_merged(int pos, const struct checkout *state)
232232
if (!ce)
233233
die(_("make_cache_entry failed for path '%s'"), path);
234234
status = checkout_entry(ce, state, NULL);
235+
free(ce);
235236
return status;
236237
}
237238

builtin/difftool.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ static void changed_files(struct hashmap *result, const char *index_path,
226226
hashmap_entry_init(entry, strhash(buf.buf));
227227
hashmap_add(result, entry);
228228
}
229+
fclose(fp);
229230
if (finish_command(&diff_files))
230231
die("diff-files did not exit properly");
231232
strbuf_release(&index_env);
@@ -456,6 +457,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
456457
}
457458
}
458459

460+
fclose(fp);
459461
if (finish_command(&child)) {
460462
ret = error("error occurred running diff --raw");
461463
goto finish;

builtin/fast-export.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@ static void handle_tag(const char *name, struct tag *tag)
765765
(int)(tagger_end - tagger), tagger,
766766
tagger == tagger_end ? "" : "\n",
767767
(int)message_size, (int)message_size, message ? message : "");
768+
free(buf);
768769
}
769770

770771
static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)

builtin/mailsplit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
232232

233233
do {
234234
peek = fgetc(f);
235-
} while (isspace(peek));
235+
} while (peek >= 0 && isspace(peek));
236236
ungetc(peek, f);
237237

238238
if (strbuf_getwholeline(&buf, f, '\n')) {

builtin/mktree.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
7272
unsigned mode;
7373
enum object_type mode_type; /* object type derived from mode */
7474
enum object_type obj_type; /* object type derived from sha */
75-
char *path;
75+
char *path, *p = NULL;
7676
unsigned char sha1[20];
7777

7878
ptr = buf;
@@ -102,7 +102,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
102102
struct strbuf p_uq = STRBUF_INIT;
103103
if (unquote_c_style(&p_uq, path, NULL))
104104
die("invalid quoting");
105-
path = strbuf_detach(&p_uq, NULL);
105+
path = p = strbuf_detach(&p_uq, NULL);
106106
}
107107

108108
/*
@@ -136,6 +136,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss
136136
}
137137

138138
append_to_tree(mode, sha1, path);
139+
free(p);
139140
}
140141

141142
int cmd_mktree(int ac, const char **av, const char *prefix)

builtin/name-rev.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ static void name_rev(struct commit *commit,
2828
struct rev_name *name = (struct rev_name *)commit->util;
2929
struct commit_list *parents;
3030
int parent_number = 1;
31+
char *p = NULL;
3132

3233
parse_commit(commit);
3334

3435
if (commit->date < cutoff)
3536
return;
3637

3738
if (deref) {
38-
tip_name = xstrfmt("%s^0", tip_name);
39+
tip_name = p = xstrfmt("%s^0", tip_name);
3940

4041
if (generation)
4142
die("generation: %d, but deref?", generation);
@@ -53,8 +54,10 @@ static void name_rev(struct commit *commit,
5354
name->taggerdate = taggerdate;
5455
name->generation = generation;
5556
name->distance = distance;
56-
} else
57+
} else {
58+
free(p);
5759
return;
60+
}
5861

5962
for (parents = commit->parents;
6063
parents;

builtin/pack-redundant.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ static void minimize(struct pack_list **min)
442442
/* return if there are no objects missing from the unique set */
443443
if (missing->size == 0) {
444444
*min = unique;
445+
free(missing);
445446
return;
446447
}
447448

builtin/receive-pack.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,8 @@ static const char *update(struct command *cmd, struct shallow_info *si)
984984
{
985985
const char *name = cmd->ref_name;
986986
struct strbuf namespaced_name_buf = STRBUF_INIT;
987-
const char *namespaced_name, *ret;
987+
static char *namespaced_name;
988+
const char *ret;
988989
unsigned char *old_sha1 = cmd->old_sha1;
989990
unsigned char *new_sha1 = cmd->new_sha1;
990991

@@ -995,6 +996,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
995996
}
996997

997998
strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name);
999+
free(namespaced_name);
9981000
namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);
9991001

10001002
if (is_ref_checked_out(namespaced_name)) {

builtin/worktree.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,11 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
408408
find_unique_abbrev(wt->head_sha1, DEFAULT_ABBREV));
409409
if (wt->is_detached)
410410
strbuf_addstr(&sb, "(detached HEAD)");
411-
else if (wt->head_ref)
412-
strbuf_addf(&sb, "[%s]", shorten_unambiguous_ref(wt->head_ref, 0));
413-
else
411+
else if (wt->head_ref) {
412+
char *ref = shorten_unambiguous_ref(wt->head_ref, 0);
413+
strbuf_addf(&sb, "[%s]", ref);
414+
free(ref);
415+
} else
414416
strbuf_addstr(&sb, "(error)");
415417
}
416418
printf("%s\n", sb.buf);

compat/mingw.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,8 +1172,10 @@ static char **get_path_split(void)
11721172
++n;
11731173
}
11741174
}
1175-
if (!n)
1175+
if (!n) {
1176+
free(envpath);
11761177
return NULL;
1178+
}
11771179

11781180
ALLOC_ARRAY(path, n + 1);
11791181
p = envpath;
@@ -1566,12 +1568,18 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
15661568

15671569
if (getenv("GIT_STRACE_COMMANDS")) {
15681570
char **path = get_path_split();
1569-
cmd = path_lookup("strace.exe", path, 1);
1570-
if (!cmd)
1571+
char *p = path_lookup("strace.exe", path, 1);
1572+
if (!p) {
1573+
free_path_split(path);
15711574
return error("strace not found!");
1572-
if (xutftowcs_path(wcmd, cmd) < 0)
1575+
}
1576+
free_path_split(path);
1577+
if (xutftowcs_path(wcmd, p) < 0) {
1578+
free(p);
15731579
return -1;
1580+
}
15741581
strbuf_insert(&args, 0, "strace ", 7);
1582+
free(p);
15751583
}
15761584

15771585
ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));

compat/winansi.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ static int is_console(int fd)
100100
if (!fd) {
101101
if (!GetConsoleMode(hcon, &mode))
102102
return 0;
103+
sbi.wAttributes = FOREGROUND_BLUE | FOREGROUND_GREEN |
104+
FOREGROUND_RED;
103105
} else if (!GetConsoleScreenBufferInfo(hcon, &sbi))
104106
return 0;
105107

@@ -128,6 +130,11 @@ static void write_console(unsigned char *str, size_t len)
128130

129131
/* convert utf-8 to utf-16 */
130132
int wlen = xutftowcsn(wbuf, (char*) str, ARRAY_SIZE(wbuf), len);
133+
if (wlen < 0) {
134+
wchar_t *err = L"[invalid]";
135+
WriteConsoleW(console, err, wcslen(err), &dummy, NULL);
136+
return;
137+
}
131138

132139
/* write directly to console */
133140
WriteConsoleW(console, wbuf, wlen, &dummy, NULL);

config.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2426,7 +2426,7 @@ int git_config_rename_section_in_file(const char *config_filename,
24262426
struct lock_file *lock;
24272427
int out_fd;
24282428
char buf[1024];
2429-
FILE *config_file;
2429+
FILE *config_file = NULL;
24302430
struct stat st;
24312431

24322432
if (new_name && !section_name_is_ok(new_name)) {
@@ -2508,11 +2508,14 @@ int git_config_rename_section_in_file(const char *config_filename,
25082508
}
25092509
}
25102510
fclose(config_file);
2511+
config_file = NULL;
25112512
commit_and_out:
25122513
if (commit_lock_file(lock) < 0)
25132514
ret = error_errno("could not write config file %s",
25142515
config_filename);
25152516
out:
2517+
if (config_file)
2518+
fclose(config_file);
25162519
rollback_lock_file(lock);
25172520
out_no_rollback:
25182521
free(filename_buf);

connect.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,10 @@ static int handle_ssh_variant(const char *ssh_command, int is_cmdline,
716716
* any longer.
717717
*/
718718
free(ssh_argv);
719-
} else
719+
} else {
720+
free(ssh_argv);
720721
return 0;
722+
}
721723
}
722724

723725
if (!strcasecmp(variant, "plink") ||

http-backend.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,10 @@ int cmd_main(int argc, const char **argv)
681681
if (!regexec(&re, dir, 1, out, 0)) {
682682
size_t n;
683683

684-
if (strcmp(method, c->method))
684+
if (strcmp(method, c->method)) {
685+
free(dir);
685686
return bad_request(&hdr, c);
687+
}
686688

687689
cmd = c;
688690
n = out[0].rm_eo - out[0].rm_so;
@@ -708,5 +710,7 @@ int cmd_main(int argc, const char **argv)
708710
max_request_buffer);
709711

710712
cmd->imp(&hdr, cmd_arg);
713+
free(dir);
714+
free(cmd_arg);
711715
return 0;
712716
}

ident.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,10 @@ const char *ident_default_email(void)
169169
strbuf_addstr(&git_default_email, email);
170170
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
171171
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
172-
} else if ((email = query_user_email()) && email[0])
172+
} else if ((email = query_user_email()) && email[0]) {
173173
strbuf_addstr(&git_default_email, email);
174-
else
174+
free((char *)email);
175+
} else
175176
copy_email(xgetpwuid_self(&default_email_is_bogus),
176177
&git_default_email, &default_email_is_bogus);
177178
strbuf_trim(&git_default_email);

line-log.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
11251125
changed = process_all_files(&parent_range, rev, &queue, range);
11261126
if (parent)
11271127
add_line_range(rev, parent, parent_range);
1128+
free(parent_range);
11281129
return changed;
11291130
}
11301131

mailinfo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ int mailinfo(struct mailinfo *mi, const char *msg, const char *patch)
10941094

10951095
do {
10961096
peek = fgetc(mi->input);
1097-
} while (isspace(peek));
1097+
} while (peek >= 0 && isspace(peek));
10981098
ungetc(peek, mi->input);
10991099

11001100
/* process the email header */

patch-ids.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,12 @@ struct patch_id *has_commit_patch_id(struct commit *commit,
9999
struct patch_id *add_commit_patch_id(struct commit *commit,
100100
struct patch_ids *ids)
101101
{
102-
struct patch_id *key = xcalloc(1, sizeof(*key));
102+
struct patch_id *key;
103103

104104
if (!patch_id_defined(commit))
105105
return NULL;
106106

107+
key = xcalloc(1, sizeof(*key));
107108
if (init_patch_id_entry(key, commit, ids)) {
108109
free(key);
109110
return NULL;

reflog-walk.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
183183
if (!reflogs || reflogs->nr == 0) {
184184
unsigned char sha1[20];
185185
char *b;
186-
if (dwim_log(branch, strlen(branch), sha1, &b) == 1) {
186+
int ret = dwim_log(branch, strlen(branch), sha1, &b);
187+
if (ret > 1)
188+
free(b);
189+
else if (ret == 1) {
187190
if (reflogs) {
188191
free(reflogs->ref);
189192
free(reflogs);

remote.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,9 +1191,10 @@ static int match_explicit(struct ref *src, struct ref *dst,
11911191
else if (is_null_oid(&matched_src->new_oid))
11921192
error("unable to delete '%s': remote ref does not exist",
11931193
dst_value);
1194-
else if ((dst_guess = guess_ref(dst_value, matched_src)))
1194+
else if ((dst_guess = guess_ref(dst_value, matched_src))) {
11951195
matched_dst = make_linked_ref(dst_guess, dst_tail);
1196-
else
1196+
free(dst_guess);
1197+
} else
11971198
error("unable to push to unqualified destination: %s\n"
11981199
"The destination refspec neither matches an "
11991200
"existing ref on the remote nor\n"

sequencer.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,11 +2678,13 @@ int skip_unnecessary_picks(void)
26782678
if (write_in_full(fd, todo_list.buf.buf + offset,
26792679
todo_list.buf.len - offset) < 0) {
26802680
todo_list_release(&todo_list);
2681+
close(fd);
26812682
return error_errno(_("could not write to '%s'"),
26822683
rebase_path_todo());
26832684
}
26842685
if (ftruncate(fd, todo_list.buf.len - offset) < 0) {
26852686
todo_list_release(&todo_list);
2687+
close(fd);
26862688
return error_errno(_("could not truncate '%s'"),
26872689
rebase_path_todo());
26882690
}

0 commit comments

Comments
 (0)