Thread (36 messages) 36 messages, 2 authors, 6d ago

Re: [PATCH 10/11] bisect: ensure non-NULL `head` before using it

From: Junio C Hamano <hidden>
Date: 2026-07-10 04:01:05

"Johannes Schindelin via GitGitGadget" [off-list ref]
writes:
When `refs_resolve_ref_unsafe()` is called to resolve HEAD, and returns
NULL (e.g., HEAD does not exist as a proper ref), the code falls back to
`repo_get_oid("HEAD")` to try to resolve the OID directly. If that
succeeds, execution continues with `head` still set to NULL.

Later, that variable is passed to `repo_get_oid()` and `starts_with()`,
both of which would dereference the NULL pointer.

The scenario "`refs_resolve_ref_unsafe()` returns NULL but
`repo_get_oid()` succeeds" can happen when HEAD is a detached bare OID
that the ref backend cannot resolve symbolically (a potential edge case
with the reftable backend) but the OID itself is valid. In this case,
the bisect-start file does not yet exist (this is a fresh "git bisect
start"), so the else branch is taken with the NULL `head`.
I agree that setting head to the string "HEAD" is a good solution to
ensure that !starts_with(), !repo_get_oid(), and skip_prefix() are
not called with NULL.

However, I am not sure I understand your "can happen" scenario.

I naively thought that the only case where HEAD does not resolve to
an object correctly is when HEAD is a symbolic ref pointing to an
unborn branch.

Is the bug in your "can happen" scenario something we can
demonstrate?  If so, could you add a test to prevent regressions in
the future?

Thanks.

quoted hunk ↗ jump to hunk
Simply assign "HEAD" to `head` as a fallback to address this.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <redacted>
---
 builtin/bisect.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 6ff600c856..a69771c6d3 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -811,9 +811,11 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
 	 */
 	head = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
 				       "HEAD", 0, &head_oid, &flags);
-	if (!head)
+	if (!head) {
 		if (repo_get_oid(the_repository, "HEAD", &head_oid))
 			return error(_("bad HEAD - I need a HEAD"));
+		head = "HEAD";
+	}
 
 	/*
 	 * Check if we are bisecting
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help