Merge branch 'js/coverity-unchecked-returns-fix'

A handful of code paths have been corrected to check return values
from functions like curl_easy_duphandle(), deflateInit(), lseek(),
dup(), and strbuf_getline_lf(), resolving several Coverity warnings
about unchecked returns.

* js/coverity-unchecked-returns-fix:
  bisect: handle dup() failure when redirecting stdout
  bisect: check get_terms return at all call sites
  bisect: check strbuf_getline_lf return when reading terms
  transport-helper: warn when export-marks file cannot be finalized
  transport-helper: check dup() return in get_exporter
  compat/pread: check initial lseek for errors
  last-modified: handle repo_parse_commit() failures
  reftable tests: check reftable_table_init_ref_iterator() return
  reftable/block: check deflateInit() return value
  reftable: handle block-writer initialization errors
  config: propagate launch_editor() failure in show_editor()
  http: die on curl_easy_duphandle failure in get_active_slot
main
Junio C Hamano 2026-08-24 13:17:50 -07:00
commit fcc8c931b5
10 changed files with 70 additions and 23 deletions

View File

@ -1020,10 +1020,12 @@ void read_bisect_terms(char **read_bad, char **read_good)
die_errno(_("could not read file '%s'"), filename); die_errno(_("could not read file '%s'"), filename);
} }
} else { } else {
strbuf_getline_lf(&str, fp); if (strbuf_getline_lf(&str, fp) == EOF)
die(_("could not read bad term from file '%s'"), filename);
free(*read_bad); free(*read_bad);
*read_bad = strbuf_detach(&str, NULL); *read_bad = strbuf_detach(&str, NULL);
strbuf_getline_lf(&str, fp); if (strbuf_getline_lf(&str, fp) == EOF)
die(_("could not read good term from file '%s'"), filename);
free(*read_good); free(*read_good);
*read_good = strbuf_detach(&str, NULL); *read_good = strbuf_detach(&str, NULL);
} }

View File

@ -566,7 +566,7 @@ static int bisect_next_check(const struct bisect_terms *terms,
return decide_next(terms, current_term, !state.nr_good, !state.nr_bad); return decide_next(terms, current_term, !state.nr_good, !state.nr_bad);
} }


static int get_terms(struct bisect_terms *terms) static int get_terms(struct bisect_terms *terms, int file_missing_is_ok)
{ {
struct strbuf str = STRBUF_INIT; struct strbuf str = STRBUF_INIT;
FILE *fp = NULL; FILE *fp = NULL;
@ -574,14 +574,21 @@ static int get_terms(struct bisect_terms *terms)


fp = fopen(git_path_bisect_terms(), "r"); fp = fopen(git_path_bisect_terms(), "r");
if (!fp) { if (!fp) {
res = -1; res = file_missing_is_ok ? 0 : -1;
goto finish; goto finish;
} }


free_terms(terms); free_terms(terms);
strbuf_getline_lf(&str, fp); if (strbuf_getline_lf(&str, fp) == EOF) {
res = -1;
goto finish;
}
terms->term_bad = strbuf_detach(&str, NULL); terms->term_bad = strbuf_detach(&str, NULL);
strbuf_getline_lf(&str, fp); if (strbuf_getline_lf(&str, fp) == EOF) {
res = -1;
FREE_AND_NULL(terms->term_bad);
goto finish;
}
terms->term_good = strbuf_detach(&str, NULL); terms->term_good = strbuf_detach(&str, NULL);


finish: finish:
@ -593,7 +600,7 @@ finish:


static int bisect_terms(struct bisect_terms *terms, const char *option) static int bisect_terms(struct bisect_terms *terms, const char *option)
{ {
if (get_terms(terms)) if (get_terms(terms, 0))
return error(_("no terms defined")); return error(_("no terms defined"));


if (!option) { if (!option) {
@ -1157,7 +1164,8 @@ static int process_replay_line(struct bisect_terms *terms, struct strbuf *line)
rev = word_end + strspn(word_end, " \t"); rev = word_end + strspn(word_end, " \t");
*word_end = '\0'; /* NUL-terminate the word */ *word_end = '\0'; /* NUL-terminate the word */


get_terms(terms); if (get_terms(terms, 1))
return error(_("no terms defined"));
if (check_and_set_terms(terms, p)) if (check_and_set_terms(terms, p))
return -1; return -1;


@ -1430,7 +1438,14 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)


fflush(stdout); fflush(stdout);
saved_stdout = dup(1); saved_stdout = dup(1);
dup2(temporary_stdout_fd, 1); if (saved_stdout < 0 ||
dup2(temporary_stdout_fd, 1) < 0) {
res = error_errno(_("could not duplicate stdout"));
if (saved_stdout >= 0)
close(saved_stdout);
close(temporary_stdout_fd);
break;
}


res = bisect_state(terms, 1, &new_state); res = bisect_state(terms, 1, &new_state);


@ -1510,7 +1525,8 @@ static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *pref
if (argc) if (argc)
return error(_("'%s' requires 0 arguments"), return error(_("'%s' requires 0 arguments"),
"git bisect next"); "git bisect next");
get_terms(&terms); if (get_terms(&terms, 1))
return error(_("no terms defined"));
res = bisect_next(&terms, prefix); res = bisect_next(&terms, prefix);
free_terms(&terms); free_terms(&terms);
return res; return res;
@ -1544,7 +1560,8 @@ static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUS
struct bisect_terms terms = { 0 }; struct bisect_terms terms = { 0 };


set_terms(&terms, "bad", "good"); set_terms(&terms, "bad", "good");
get_terms(&terms); if (get_terms(&terms, 1))
return error(_("no terms defined"));
res = bisect_skip(&terms, argc, argv); res = bisect_skip(&terms, argc, argv);
free_terms(&terms); free_terms(&terms);
return res; return res;
@ -1556,7 +1573,8 @@ static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix
int res; int res;
struct bisect_terms terms = { 0 }; struct bisect_terms terms = { 0 };


get_terms(&terms); if (get_terms(&terms, 1))
return error(_("no terms defined"));
res = bisect_visualize(&terms, argc, argv); res = bisect_visualize(&terms, argc, argv);
free_terms(&terms); free_terms(&terms);
return res; return res;
@ -1570,7 +1588,8 @@ static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSE


if (!argc) if (!argc)
return error(_("'%s' failed: no command provided."), "git bisect run"); return error(_("'%s' failed: no command provided."), "git bisect run");
get_terms(&terms); if (get_terms(&terms, 1))
return error(_("no terms defined"));
res = bisect_run(&terms, argc, argv); res = bisect_run(&terms, argc, argv);
free_terms(&terms); free_terms(&terms);
return res; return res;
@ -1609,7 +1628,8 @@ int cmd_bisect(int argc,
usage_with_options(git_bisect_usage, options); usage_with_options(git_bisect_usage, options);


set_terms(&terms, "bad", "good"); set_terms(&terms, "bad", "good");
get_terms(&terms); if (get_terms(&terms, 1))
return error(_("no terms defined"));
if (check_and_set_terms(&terms, argv[0]) || if (check_and_set_terms(&terms, argv[0]) ||
!one_of(argv[0], terms.term_good, terms.term_bad, NULL)) !one_of(argv[0], terms.term_good, terms.term_bad, NULL))
usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage, usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage,

View File

@ -1313,7 +1313,10 @@ static int show_editor(struct config_location_options *opts)
else if (errno != EEXIST) else if (errno != EEXIST)
die_errno(_("cannot create configuration file %s"), config_file); die_errno(_("cannot create configuration file %s"), config_file);
} }
launch_editor(config_file, NULL, NULL); if (launch_editor(config_file, NULL, NULL)) {
free(config_file);
return -1;
}
free(config_file); free(config_file);


return 0; return 0;

View File

@ -290,7 +290,8 @@ static void process_parent(struct last_modified *lm,
{ {
struct bitmap *active_p; struct bitmap *active_p;


repo_parse_commit(lm->rev.repo, parent); if (repo_parse_commit(lm->rev.repo, parent))
return;
active_p = active_paths_for(lm, parent); active_p = active_paths_for(lm, parent);


/* /*
@ -414,12 +415,14 @@ static int last_modified_run(struct last_modified *lm)
* Otherwise, make sure that 'c' isn't reachable from anything * Otherwise, make sure that 'c' isn't reachable from anything
* in the '--not' queue. * in the '--not' queue.
*/ */
repo_parse_commit(lm->rev.repo, c); if (repo_parse_commit(lm->rev.repo, c))
goto cleanup;


while ((n = prio_queue_get(&not_queue))) { while ((n = prio_queue_get(&not_queue))) {
struct commit_list *np; struct commit_list *np;


repo_parse_commit(lm->rev.repo, n); if (repo_parse_commit(lm->rev.repo, n))
continue;


for (np = n->parents; np; np = np->next) { for (np = n->parents; np; np = np->next) {
if (!(np->item->object.flags & PARENT2)) { if (!(np->item->object.flags & PARENT2)) {

View File

@ -7,6 +7,8 @@ ssize_t git_pread(int fd, void *buf, size_t count, off_t offset)
ssize_t rc; ssize_t rc;


current_offset = lseek(fd, 0, SEEK_CUR); current_offset = lseek(fd, 0, SEEK_CUR);
if (current_offset < 0)
return -1;


if (lseek(fd, offset, SEEK_SET) < 0) if (lseek(fd, offset, SEEK_SET) < 0)
return -1; return -1;

2
http.c
View File

@ -1608,6 +1608,8 @@ struct active_request_slot *get_active_slot(void)


if (!slot->curl) { if (!slot->curl) {
slot->curl = curl_easy_duphandle(curl_default); slot->curl = curl_easy_duphandle(curl_default);
if (!slot->curl)
die("curl_easy_duphandle failed");
curl_session_count++; curl_session_count++;
} }



View File

@ -87,7 +87,10 @@ int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *block,
REFTABLE_CALLOC_ARRAY(bw->zstream, 1); REFTABLE_CALLOC_ARRAY(bw->zstream, 1);
if (!bw->zstream) if (!bw->zstream)
return REFTABLE_OUT_OF_MEMORY_ERROR; return REFTABLE_OUT_OF_MEMORY_ERROR;
deflateInit(bw->zstream, 9); if (deflateInit(bw->zstream, 9) != Z_OK) {
REFTABLE_FREE_AND_NULL(bw->zstream);
return REFTABLE_ZLIB_ERROR;
}
} }


return 0; return 0;

View File

@ -150,6 +150,7 @@ int reftable_writer_new(struct reftable_writer **out,
{ {
struct reftable_write_options opts = {0}; struct reftable_write_options opts = {0};
struct reftable_writer *wp; struct reftable_writer *wp;
int err;


if (_opts) if (_opts)
opts = *_opts; opts = *_opts;
@ -177,7 +178,12 @@ int reftable_writer_new(struct reftable_writer **out,
wp->opts = opts; wp->opts = opts;
wp->hash_id = hash_id; wp->hash_id = hash_id;
wp->flush = flush_func; wp->flush = flush_func;
writer_reinit_block_writer(wp, REFTABLE_BLOCK_TYPE_REF); err = writer_reinit_block_writer(wp, REFTABLE_BLOCK_TYPE_REF);
if (err < 0) {
reftable_free(wp->block);
reftable_free(wp);
return err;
}


*out = wp; *out = wp;



View File

@ -32,7 +32,8 @@ void test_reftable_table__seek_once(void)
ret = reftable_table_new(&table, &source, "name"); ret = reftable_table_new(&table, &source, "name");
cl_assert(!ret); cl_assert(!ret);


reftable_table_init_ref_iterator(table, &it); ret = reftable_table_init_ref_iterator(table, &it);
cl_assert_equal_i(ret, 0);
ret = reftable_iterator_seek_ref(&it, ""); ret = reftable_iterator_seek_ref(&it, "");
cl_assert(!ret); cl_assert(!ret);
ret = reftable_iterator_next_ref(&it, &ref); ret = reftable_iterator_next_ref(&it, &ref);
@ -74,7 +75,8 @@ void test_reftable_table__reseek(void)
ret = reftable_table_new(&table, &source, "name"); ret = reftable_table_new(&table, &source, "name");
cl_assert(!ret); cl_assert(!ret);


reftable_table_init_ref_iterator(table, &it); ret = reftable_table_init_ref_iterator(table, &it);
cl_assert_equal_i(ret, 0);


for (size_t i = 0; i < 5; i++) { for (size_t i = 0; i < 5; i++) {
ret = reftable_iterator_seek_ref(&it, ""); ret = reftable_iterator_seek_ref(&it, "");

View File

@ -487,6 +487,8 @@ static int get_exporter(struct transport *transport,
/* we need to duplicate helper->in because we want to use it after /* we need to duplicate helper->in because we want to use it after
* fastexport is done with it. */ * fastexport is done with it. */
fastexport->out = dup(helper->in); fastexport->out = dup(helper->in);
if (fastexport->out < 0)
return error_errno(_("could not dup helper output fd"));
strvec_push(&fastexport->args, "fast-export"); strvec_push(&fastexport->args, "fast-export");
strvec_push(&fastexport->args, "--use-done-feature"); strvec_push(&fastexport->args, "--use-done-feature");
strvec_push(&fastexport->args, data->signed_tags ? strvec_push(&fastexport->args, data->signed_tags ?
@ -1194,7 +1196,9 @@ static int push_refs_with_export(struct transport *transport,


if (data->export_marks) { if (data->export_marks) {
strbuf_addf(&buf, "%s.tmp", data->export_marks); strbuf_addf(&buf, "%s.tmp", data->export_marks);
rename(buf.buf, data->export_marks); if (rename(buf.buf, data->export_marks))
warning_errno(_("could not rename '%s' to '%s'"),
buf.buf, data->export_marks);
strbuf_release(&buf); strbuf_release(&buf);
} }