Merge branch 'js/coverity-fixes-null-safety' into next

Various code paths have been hardened against potential NULL-pointer
dereferences and invalid file descriptor accesses flagged by
Coverity.

* js/coverity-fixes-null-safety:
  shallow: give write_one_shallow() its own hex buffer
  shallow: fix NULL dereference
  bisect: ensure non-NULL `head` before using it
  pack-bitmap: handle missing bitmap for base MIDX
  revision: avoid dereferencing NULL in `add_parents_only()`
  replay: die when --onto does not peel to a commit
  bisect: handle NULL commit in `bisect_successful()`
  mailsplit: move NULL check before first use of file handle
  reftable/stack: guard against NULL list_file in stack_destroy
  remote: guard `remote_tracking()` against NULL remote
  diff: handle NULL return from repo_get_commit_tree()
  diffcore-break: guard against NULLed queue entries in merge loop
next
Junio C Hamano 2026-07-12 11:14:32 -07:00
commit 8d093f411d
11 changed files with 63 additions and 15 deletions

View File

@ -663,6 +663,11 @@ static int bisect_successful(struct bisect_terms *terms)

refs_read_ref(get_main_ref_store(the_repository), bad_ref, &oid);
commit = lookup_commit_reference_by_name(bad_ref);
if (!commit) {
error(_("could not find commit for '%s'"), bad_ref);
free(bad_ref);
return BISECT_FAILED;
}
repo_format_commit_message(the_repository, commit, "%s", &commit_name,
&pp);

@ -806,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

View File

@ -579,9 +579,13 @@ int cmd_diff(int argc,
obj = deref_tag(the_repository, obj, NULL, 0);
if (!obj)
die(_("invalid object '%s' given."), name);
if (obj->type == OBJ_COMMIT)
obj = &repo_get_commit_tree(the_repository,
((struct commit *)obj))->object;
if (obj->type == OBJ_COMMIT) {
struct tree *tree = repo_get_commit_tree(
the_repository, (struct commit *)obj);
if (!tree)
die(_("unable to read tree object for commit '%s'"), name);
obj = &tree->object;
}

if (obj->type == OBJ_TREE) {
if (sdiff.skip && bitmap_get(sdiff.skip, i))

View File

@ -225,14 +225,14 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r");
int file_done = 0;

if (isatty(fileno(f)))
warning(_("reading patches from stdin/tty..."));

if (!f) {
error_errno("cannot open mbox %s", file);
goto out;
}

if (isatty(fileno(f)))
warning(_("reading patches from stdin/tty..."));

do {
peek = fgetc(f);
if (peek == EOF) {

View File

@ -289,6 +289,8 @@ void diffcore_merge_broken(void)
*/
for (j = i + 1; j < q->nr; j++) {
struct diff_filepair *pp = q->queue[j];
if (!pp)
continue;
if (pp->broken_pair &&
!strcmp(pp->one->path, pp->two->path) &&
!strcmp(p->one->path, pp->two->path)) {

View File

@ -523,6 +523,10 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,

if (midx->base_midx) {
bitmap_git->base = prepare_midx_bitmap_git(midx->base_midx);
if (!bitmap_git->base) {
warning(_("could not open bitmap for base MIDX"));
goto cleanup;
}
bitmap_git->base_nr = bitmap_git->base->base_nr + 1;
} else {
bitmap_git->base_nr = 0;

View File

@ -171,7 +171,8 @@ void reftable_stack_destroy(struct reftable_stack *st)
st->merged = NULL;
}

err = read_lines(st->list_file, &names);
if (st->list_file)
err = read_lines(st->list_file, &names);
if (err < 0) {
REFTABLE_FREE_AND_NULL(names);
}

View File

@ -2713,6 +2713,8 @@ static int remote_tracking(struct remote *remote, const char *refname,
{
char *dst;

if (!remote)
BUG("remote_tracking() called with NULL remote");
dst = apply_refspecs(&remote->fetch, refname);
if (!dst)
return -1; /* no tracking ref for refname at remote */

View File

@ -36,12 +36,16 @@ static struct commit *peel_committish(struct repository *repo,
{
struct object *obj;
struct object_id oid;
struct commit *commit;

if (repo_get_oid(repo, name, &oid))
die(_("'%s' is not a valid commit-ish for %s"), name, mode);
obj = parse_object_or_die(repo, &oid, name);
return (struct commit *)repo_peel_to_type(repo, name, 0, obj,
OBJ_COMMIT);
commit = (struct commit *)repo_peel_to_type(repo, name, 0, obj,
OBJ_COMMIT);
if (!commit)
die(_("'%s' does not point to a commit for %s"), name, mode);
return commit;
}

static char *get_author(const char *message)

View File

@ -1904,8 +1904,13 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
return 0;
while (1) {
it = get_reference(revs, arg, &oid, 0);
if (!it && revs->ignore_missing)
return 0;
if (!it) {
if (revs->ignore_missing)
return 0;
if (revs->do_not_die_on_missing_objects)
return 0;
return -1;
}
if (it->type != OBJ_TAG)
break;
if (!((struct tag*)it)->tagged)

View File

@ -357,7 +357,9 @@ struct write_shallow_data {
static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
{
struct write_shallow_data *data = cb_data;
const char *hex = oid_to_hex(&graft->oid);
char hex[GIT_MAX_HEXSZ + 1];

oid_to_hex_r(hex, &graft->oid);
if (graft->nr_parent != -1)
return 0;
if (data->flags & QUICK) {
@ -368,8 +370,7 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
struct commit *c = lookup_commit(the_repository, &graft->oid);
if (!c || !(c->object.flags & SEEN)) {
if (data->flags & VERBOSE)
printf("Removing %s from .git/shallow\n",
oid_to_hex(&c->object.oid));
printf("Removing %s from .git/shallow\n", hex);
return 0;
}
}

View File

@ -489,6 +489,24 @@ test_expect_success 'rev-list dies for missing objects on cmd line' '
done
'

test_expect_success '--exclude-promisor-objects with ^@ on missing object' '
rm -rf repo &&
test_create_repo repo &&
test_commit -C repo foo &&
test_commit -C repo bar &&

COMMIT=$(git -C repo rev-parse foo) &&
promise_and_delete "$COMMIT" &&

git -C repo config core.repositoryformatversion 1 &&
git -C repo config extensions.partialclone "arbitrary string" &&

# Ensure that "$COMMIT^@" is handled gracefully even though the
# actual commits are missing.
git -C repo rev-list --exclude-promisor-objects "$COMMIT^@" >out &&
test_must_be_empty out
'

test_expect_success 'single promisor remote can be re-initialized gracefully' '
# ensure one promisor is in the promisors list
rm -rf repo &&