describe: pass commit to describe_commit()

There's a call in describe_commit() to lookup_commit_reference(), but we don't check the return value. If it returns NULL, we'll segfault as we immediately dereference the result. In practice this can never happen, since all callers pass an oid which came from a "struct commit" already. So we can make this more obvious by just taking that commit struct in the first place. Reported-by: Cheng <prophecheng@stu.pku.edu.cn> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Aug 18, 2025 at 17:04 UTC 7c10e48e81ae63974e3badf3b7df71df74a0640b
1 file changed +9 -11
builtin/describe.c
+9 -11
@@ -313,9 +313,9 @@ static void append_suffix(int depth, const struct object_id *oid, struct strbuf
313 repo_find_unique_abbrev(the_repository, oid, abbrev));
314 }
315
316 -static void describe_commit(struct object_id *oid, struct strbuf *dst)
316 +static void describe_commit(struct commit *cmit, struct strbuf *dst)
317 {
318 - struct commit *cmit, *gave_up_on = NULL;
318 + struct commit *gave_up_on = NULL;
319 struct commit_list *list;
320 struct commit_name *n;
321 struct possible_tag all_matches[MAX_TAGS];
@@ -323,8 +323,6 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
323 unsigned long seen_commits = 0;
324 unsigned int unannotated_cnt = 0;
325
326 - cmit = lookup_commit_reference(the_repository, oid);
327 -
326 n = find_commit_name(&cmit->object.oid);
327 if (n && (tags || all || n->prio == 2)) {
328 /*
@@ -332,7 +330,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
330 */
331 append_name(n, dst);
332 if (n->misnamed || longformat)
335 - append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst);
333 + append_suffix(0, n->tag ? get_tagged_oid(n->tag) : &cmit->object.oid, dst);
334 if (suffix)
335 strbuf_addstr(dst, suffix);
336 return;
@@ -489,7 +487,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
487 }
488
489 struct process_commit_data {
492 - struct object_id current_commit;
490 + struct commit *current_commit;
491 const struct object_id *looking_for;
492 struct strbuf *dst;
493 struct rev_info *revs;
@@ -498,7 +496,7 @@ struct process_commit_data {
496 static void process_commit(struct commit *commit, void *data)
497 {
498 struct process_commit_data *pcd = data;
501 - pcd->current_commit = commit->object.oid;
499 + pcd->current_commit = commit;
500 }
501
502 static void process_object(struct object *obj, const char *path, void *data)
@@ -507,8 +505,8 @@ static void process_object(struct object *obj, const char *path, void *data)
505
506 if (oideq(pcd->looking_for, &obj->oid) && !pcd->dst->len) {
507 reset_revision_walk();
510 - if (!is_null_oid(&pcd->current_commit)) {
511 - describe_commit(&pcd->current_commit, pcd->dst);
508 + if (pcd->current_commit) {
509 + describe_commit(pcd->current_commit, pcd->dst);
510 strbuf_addf(pcd->dst, ":%s", path);
511 }
512 free_commit_list(pcd->revs->commits);
@@ -521,7 +519,7 @@ static void describe_blob(const struct object_id *oid, struct strbuf *dst)
519 struct rev_info revs;
520 struct strvec args = STRVEC_INIT;
521 struct object_id head_oid;
524 - struct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};
522 + struct process_commit_data pcd = { NULL, oid, dst, &revs};
523
524 if (repo_get_oid(the_repository, "HEAD", &head_oid))
525 die(_("cannot search for blob '%s' on an unborn branch"),
@@ -562,7 +560,7 @@ static void describe(const char *arg, int last_one)
560 cmit = lookup_commit_reference_gently(the_repository, &oid, 1);
561
562 if (cmit)
565 - describe_commit(&oid, &sb);
563 + describe_commit(cmit, &sb);
564 else if (odb_read_object_info(the_repository->objects,
565 &oid, NULL) == OBJ_BLOB)
566 describe_blob(&oid, &sb);