-
Notifications
You must be signed in to change notification settings - Fork 191
coverity: fix unchecked returns #2179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 10 commits
e653255
0692704
9bf7e73
711671c
f728be4
b31e032
1792042
13ddcce
17c382f
c0827a7
2da452e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -498,9 +498,15 @@ static int get_terms(struct bisect_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); | ||
| strbuf_getline_lf(&str, fp); | ||
| if (strbuf_getline_lf(&str, fp) == EOF) { | ||
| res = -1; | ||
| goto finish; | ||
| } | ||
| terms->term_good = strbuf_detach(&str, NULL); | ||
|
|
||
| finish: | ||
|
|
@@ -1051,6 +1057,8 @@ static int process_replay_line(struct bisect_terms *terms, struct strbuf *line) | |
| *word_end = '\0'; /* NUL-terminate the word */ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Patrick Steinhardt wrote on the Git mailing list (how to reply to this email): On Tue, Jul 14, 2026 at 10:48:43PM +0000, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> Six callers of get_terms() silently discard its return value. When
> get_terms fails (missing or truncated BISECT_TERMS file), the term
> strings remain NULL or empty, causing confusing downstream
> behavior: commands like "bisect next" or "bisect run" proceed with
> empty term strings, producing nonsensical ref names (refs/bisect/
> with no suffix) and misleading error messages.
>
> Add checks at each call site so that a failed get_terms produces a
> clear "no terms defined" error, matching the pattern already used
> in bisect_terms() at line 512. The check tests the term pointers
> rather than the return value because some callers (bisect skip,
> legacy bad/good) call set_terms before get_terms, and the
> set_terms values should survive a get_terms failure.
Hm. Are there any callers that accept the case where either `term->bad`
or `term->good` are `NULL`? If not, should we maybe adapt the function
itself to return an error if so and then have all callers only ever
check for the return value of `get_term()` instead of also having to
check the result? That might also allow us to deduplicate the error
messages.
Patrick |
||
|
|
||
| get_terms(terms); | ||
| if (!terms->term_bad || !terms->term_good) | ||
| return error(_("no terms defined")); | ||
| if (check_and_set_terms(terms, p)) | ||
| return -1; | ||
|
|
||
|
|
@@ -1377,6 +1385,8 @@ static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *pref | |
| return error(_("'%s' requires 0 arguments"), | ||
| "git bisect next"); | ||
| get_terms(&terms); | ||
| if (!terms.term_bad || !terms.term_good) | ||
| return error(_("no terms defined")); | ||
| res = bisect_next(&terms, prefix); | ||
| free_terms(&terms); | ||
| return res; | ||
|
|
@@ -1411,6 +1421,8 @@ static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUS | |
|
|
||
| set_terms(&terms, "bad", "good"); | ||
| get_terms(&terms); | ||
| if (!terms.term_bad || !terms.term_good) | ||
| return error(_("no terms defined")); | ||
| res = bisect_skip(&terms, argc, argv); | ||
| free_terms(&terms); | ||
| return res; | ||
|
|
@@ -1423,6 +1435,8 @@ static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix | |
| struct bisect_terms terms = { 0 }; | ||
|
|
||
| get_terms(&terms); | ||
| if (!terms.term_bad || !terms.term_good) | ||
| return error(_("no terms defined")); | ||
| res = bisect_visualize(&terms, argc, argv); | ||
| free_terms(&terms); | ||
| return res; | ||
|
|
@@ -1437,6 +1451,8 @@ static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSE | |
| if (!argc) | ||
| return error(_("'%s' failed: no command provided."), "git bisect run"); | ||
| get_terms(&terms); | ||
| if (!terms.term_bad || !terms.term_good) | ||
| return error(_("no terms defined")); | ||
| res = bisect_run(&terms, argc, argv); | ||
| free_terms(&terms); | ||
| return res; | ||
|
|
@@ -1476,6 +1492,8 @@ int cmd_bisect(int argc, | |
|
|
||
| set_terms(&terms, "bad", "good"); | ||
| get_terms(&terms); | ||
| if (!terms.term_bad || !terms.term_good) | ||
| return error(_("no terms defined")); | ||
| if (check_and_set_terms(&terms, argv[0]) || | ||
| !one_of(argv[0], terms.term_good, terms.term_bad, NULL)) | ||
| usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1313,7 +1313,10 @@ static int show_editor(struct config_location_options *opts) | |
| else if (errno != EEXIST) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Patrick Steinhardt wrote on the Git mailing list (how to reply to this email): On Tue, Jul 14, 2026 at 10:48:35PM +0000, Johannes Schindelin via GitGitGadget wrote:
> diff --git a/builtin/config.c b/builtin/config.c
> index 8d8ec0beea..1307fdb0d6 100644
> --- a/builtin/config.c
> +++ b/builtin/config.c
> @@ -1313,7 +1313,10 @@ static int show_editor(struct config_location_options *opts)
> else if (errno != EEXIST)
> 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;
> + }
All error paths in `launch_editor()` already print an error message, so
we indeed don't have to do anything but bubble up the error here.
Patrick |
||
| 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); | ||
|
|
||
| return 0; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -290,7 +290,8 @@ static void process_parent(struct last_modified *lm, | |
| { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Junio C Hamano wrote on the Git mailing list (how to reply to this email): "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:
> Skip unparsable commits by checking the return value and
> continuing to the next iteration (or returning early in
> process_parent). This matches the defensive pattern used in other
> revision walkers such as limit_list() and get_revision_internal().
> ...
> @@ -414,12 +415,14 @@ static int last_modified_run(struct last_modified *lm)
> * Otherwise, make sure that 'c' isn't reachable from anything
> * in the '--not' queue.
> */
> - repo_parse_commit(lm->rev.repo, c);
> + if (repo_parse_commit(lm->rev.repo, c))
> + continue;
Shouldn't this be
goto cleanup;
instead? 'n' pulled out of not_queue may be unparseable and when we
ignore it, don't we still want to clean up the active_paths slab for
commit 'c'?
> while ((n = prio_queue_get(¬_queue))) {
> 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) {
> if (!(np->item->object.flags & PARENT2)) {There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Junio C Hamano wrote on the Git mailing list (how to reply to this email): Junio C Hamano <gitster@pobox.com> writes:
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
> ...
>> - repo_parse_commit(lm->rev.repo, c);
>> + if (repo_parse_commit(lm->rev.repo, c))
>> + continue;
>
> Shouldn't this be
>
> goto cleanup;
>
> instead? 'n' pulled out of not_queue may be unparseable and when we
> ignore it, don't we still want to clean up the active_paths slab for
> commit 'c'?
--- >8 ---
Subject: [PATCH] fixup! last-modified: handle repo_parse_commit() failures
https://lore.kernel.org/git/xmqqldbdqciy.fsf@gitster.g/
'n' pulled out of not_queue may be unparseable and when we ignore
it, we still want to clean up the active_paths slab for commit 'c'.
diff --git a/builtin/last-modified.c b/builtin/last-modified.c
index fe012b0c2e..3846244dfc 100644
--- a/builtin/last-modified.c
+++ b/builtin/last-modified.c
@@ -416,7 +416,7 @@ static int last_modified_run(struct last_modified *lm)
* in the '--not' queue.
*/
if (repo_parse_commit(lm->rev.repo, c))
- continue;
+ goto cleanup;
while ((n = prio_queue_get(¬_queue))) {
struct commit_list *np; |
||
| 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); | ||
|
|
||
| /* | ||
|
|
@@ -414,12 +415,14 @@ static int last_modified_run(struct last_modified *lm) | |
| * Otherwise, make sure that 'c' isn't reachable from anything | ||
| * in the '--not' queue. | ||
| */ | ||
| repo_parse_commit(lm->rev.repo, c); | ||
| if (repo_parse_commit(lm->rev.repo, c)) | ||
| continue; | ||
|
|
||
| while ((n = prio_queue_get(¬_queue))) { | ||
| 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) { | ||
| if (!(np->item->object.flags & PARENT2)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ ssize_t git_pread(int fd, void *buf, size_t count, off_t offset) | |
| ssize_t rc; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Patrick Steinhardt wrote on the Git mailing list (how to reply to this email): On Tue, Jul 14, 2026 at 10:48:39PM +0000, Johannes Schindelin via GitGitGadget wrote:
> diff --git a/compat/pread.c b/compat/pread.c
> index 484e6d4c71..ac7d058cb8 100644
> --- a/compat/pread.c
> +++ b/compat/pread.c
> @@ -7,6 +7,8 @@ ssize_t git_pread(int fd, void *buf, size_t count, off_t offset)
> ssize_t rc;
>
> current_offset = lseek(fd, 0, SEEK_CUR);
> + if (current_offset < 0)
> + return -1;
>
> if (lseek(fd, offset, SEEK_SET) < 0)
> return -1;
Heh, funny. I wanted to complain about misindentation here, but your new
code is actually indented correctly. It's everything else in this file
that is indented with spaces.
Patrick |
||
|
|
||
| current_offset = lseek(fd, 0, SEEK_CUR); | ||
| if (current_offset < 0) | ||
| return -1; | ||
|
|
||
| if (lseek(fd, offset, SEEK_SET) < 0) | ||
| return -1; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -487,6 +487,8 @@ static int get_exporter(struct transport *transport, | |
| /* we need to duplicate helper->in because we want to use it after | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Patrick Steinhardt wrote on the Git mailing list (how to reply to this email): On Tue, Jul 14, 2026 at 10:48:40PM +0000, Johannes Schindelin via GitGitGadget wrote:
> diff --git a/transport-helper.c b/transport-helper.c
> index 80f90eb7ba..31883b244e 100644
> --- a/transport-helper.c
> +++ b/transport-helper.c
> @@ -487,6 +487,8 @@ static int get_exporter(struct transport *transport,
> /* we need to duplicate helper->in because we want to use it after
> * fastexport is done with it. */
> 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, "--use-done-feature");
> strvec_push(&fastexport->args, data->signed_tags ?
Makes sense. The only caller already knows to die in case it sees a
non-zero return value.
Patrick |
||
| * fastexport is done with it. */ | ||
| 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, "--use-done-feature"); | ||
| strvec_push(&fastexport->args, data->signed_tags ? | ||
|
|
@@ -1182,7 +1184,9 @@ static int push_refs_with_export(struct transport *transport, | |
|
|
||
| if (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); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Junio C Hamano wrote on the Git mailing list (how to reply to this email):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Junio C Hamano wrote on the Git mailing list (how to reply to this email):