All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Patrick Steinhardt <ps@pks.im>, Jeff King <peff@peff.net>,
	Johannes Schindelin <johannes.schindelin@gmx.de>,
	Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH v3 11/12] bisect: check get_terms return at all call sites
Date: Wed, 12 Aug 2026 08:03:19 +0000	[thread overview]
Message-ID: <aefdbe2bdfe7509e1660aa55e46bbdb79ddf619c.1786521801.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2179.v3.git.1786521801.gitgitgadget@gmail.com>

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.

Let's not discard the return value, but handle an error with the same
message `bisect_terms()` already uses when reading the terms failed.

Pointed out by Coverity.

There is one slight complication here: One caller _needs_ the return
value to indicate an error when the `BISECT_TERMS` file is absent, all
the other call sites are totally okay with a "missing" `BISECT_TERMS`
file. To address that, extend the function signature of `get_terms()` to
indicate which behavior the caller wants.

Assisted-by: Claude Opus 4.6
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/bisect.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/builtin/bisect.c b/builtin/bisect.c
index 69ab7ea248..ceb60b0626 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -485,7 +485,7 @@ static int bisect_next_check(const struct bisect_terms *terms,
 	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;
 	FILE *fp = NULL;
@@ -493,7 +493,7 @@ static int get_terms(struct bisect_terms *terms)
 
 	fp = fopen(git_path_bisect_terms(), "r");
 	if (!fp) {
-		res = -1;
+		res = file_missing_is_ok ? 0 : -1;
 		goto finish;
 	}
 
@@ -519,7 +519,7 @@ finish:
 
 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"));
 
 	if (!option) {
@@ -1057,7 +1057,8 @@ static int process_replay_line(struct bisect_terms *terms, struct strbuf *line)
 	rev = word_end + strspn(word_end, " \t");
 	*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))
 		return -1;
 
@@ -1383,7 +1384,8 @@ static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *pref
 	if (argc)
 		return error(_("'%s' requires 0 arguments"),
 			     "git bisect next");
-	get_terms(&terms);
+	if (get_terms(&terms, 1))
+		return error(_("no terms defined"));
 	res = bisect_next(&terms, prefix);
 	free_terms(&terms);
 	return res;
@@ -1417,7 +1419,8 @@ static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUS
 	struct bisect_terms terms = { 0 };
 
 	set_terms(&terms, "bad", "good");
-	get_terms(&terms);
+	if (get_terms(&terms, 1))
+		return error(_("no terms defined"));
 	res = bisect_skip(&terms, argc, argv);
 	free_terms(&terms);
 	return res;
@@ -1429,7 +1432,8 @@ static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix
 	int res;
 	struct bisect_terms terms = { 0 };
 
-	get_terms(&terms);
+	if (get_terms(&terms, 1))
+		return error(_("no terms defined"));
 	res = bisect_visualize(&terms, argc, argv);
 	free_terms(&terms);
 	return res;
@@ -1443,7 +1447,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 (get_terms(&terms, 1))
+		return error(_("no terms defined"));
 	res = bisect_run(&terms, argc, argv);
 	free_terms(&terms);
 	return res;
@@ -1482,7 +1487,8 @@ int cmd_bisect(int argc,
 			usage_with_options(git_bisect_usage, options);
 
 		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]) ||
 		    !one_of(argv[0], terms.term_good, terms.term_bad, NULL))
 			usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage,
-- 
gitgitgadget


  parent reply	other threads:[~2026-08-12  8:03 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14 22:48 [PATCH 00/11] coverity: fix unchecked returns Johannes Schindelin via GitGitGadget
2026-07-14 22:48 ` [PATCH 01/11] http: die on curl_easy_duphandle failure in get_active_slot Johannes Schindelin via GitGitGadget
2026-07-14 22:48 ` [PATCH 02/11] config: propagate launch_editor() failure in show_editor() Johannes Schindelin via GitGitGadget
2026-07-15  6:58   ` Patrick Steinhardt
2026-07-14 22:48 ` [PATCH 03/11] reftable/block: check deflateInit() return value Johannes Schindelin via GitGitGadget
2026-07-14 22:48 ` [PATCH 04/11] reftable tests: check reftable_table_init_ref_iterator() return Johannes Schindelin via GitGitGadget
2026-07-14 22:48 ` [PATCH 05/11] last-modified: handle repo_parse_commit() failures Johannes Schindelin via GitGitGadget
2026-07-15  1:15   ` Junio C Hamano
2026-07-20  5:09     ` Junio C Hamano
2026-08-05 14:27       ` Johannes Schindelin
2026-07-14 22:48 ` [PATCH 06/11] compat/pread: check initial lseek for errors Johannes Schindelin via GitGitGadget
2026-07-15  6:58   ` Patrick Steinhardt
2026-08-05 14:29     ` Johannes Schindelin
2026-07-14 22:48 ` [PATCH 07/11] transport-helper: check dup() return in get_exporter Johannes Schindelin via GitGitGadget
2026-07-15  6:58   ` Patrick Steinhardt
2026-07-14 22:48 ` [PATCH 08/11] transport-helper: warn when export-marks file cannot be finalized Johannes Schindelin via GitGitGadget
2026-07-14 22:48 ` [PATCH 09/11] bisect: check strbuf_getline_lf return when reading terms Johannes Schindelin via GitGitGadget
2026-07-15  1:17   ` Junio C Hamano
2026-07-20  5:09     ` Junio C Hamano
2026-08-05 14:33       ` Johannes Schindelin
2026-07-14 22:48 ` [PATCH 10/11] bisect: check get_terms return at all call sites Johannes Schindelin via GitGitGadget
2026-07-15  6:58   ` Patrick Steinhardt
2026-08-05 14:57     ` Johannes Schindelin
2026-07-14 22:48 ` [PATCH 11/11] bisect: handle dup() failure when redirecting stdout Johannes Schindelin via GitGitGadget
2026-07-15  6:58   ` Patrick Steinhardt
2026-08-05 16:44     ` Johannes Schindelin
2026-08-05 18:30 ` [PATCH v2 00/11] coverity: fix unchecked returns Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 01/11] http: die on curl_easy_duphandle failure in get_active_slot Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 02/11] config: propagate launch_editor() failure in show_editor() Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 03/11] reftable/block: check deflateInit() return value Johannes Schindelin via GitGitGadget
2026-08-06  1:11     ` Junio C Hamano
2026-08-05 18:30   ` [PATCH v2 04/11] reftable tests: check reftable_table_init_ref_iterator() return Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 05/11] last-modified: handle repo_parse_commit() failures Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 06/11] compat/pread: check initial lseek for errors Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 07/11] transport-helper: check dup() return in get_exporter Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 08/11] transport-helper: warn when export-marks file cannot be finalized Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 09/11] bisect: check strbuf_getline_lf return when reading terms Johannes Schindelin via GitGitGadget
2026-08-05 18:30   ` [PATCH v2 10/11] bisect: check get_terms return at all call sites Johannes Schindelin via GitGitGadget
2026-08-05 20:26     ` Junio C Hamano
2026-08-05 18:31   ` [PATCH v2 11/11] bisect: handle dup() failure when redirecting stdout Johannes Schindelin via GitGitGadget
2026-08-06 15:41     ` Jeff King
2026-08-06 17:31       ` Junio C Hamano
2026-08-12  8:03 ` [PATCH v3 00/12] coverity: fix unchecked returns Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 01/12] http: die on curl_easy_duphandle failure in get_active_slot Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 02/12] config: propagate launch_editor() failure in show_editor() Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 03/12] reftable: handle block-writer initialization errors Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 04/12] reftable/block: check deflateInit() return value Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 05/12] reftable tests: check reftable_table_init_ref_iterator() return Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 06/12] last-modified: handle repo_parse_commit() failures Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 07/12] compat/pread: check initial lseek for errors Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 08/12] transport-helper: check dup() return in get_exporter Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 09/12] transport-helper: warn when export-marks file cannot be finalized Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` [PATCH v3 10/12] bisect: check strbuf_getline_lf return when reading terms Johannes Schindelin via GitGitGadget
2026-08-12  8:03   ` Johannes Schindelin via GitGitGadget [this message]
2026-08-12  8:03   ` [PATCH v3 12/12] bisect: handle dup() failure when redirecting stdout Johannes Schindelin via GitGitGadget

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aefdbe2bdfe7509e1660aa55e46bbdb79ddf619c.1786521801.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=johannes.schindelin@gmx.de \
    --cc=peff@peff.net \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.