Merge branch 'dk/reflog-walk-with-non-commit'
authorJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2016 19:43:32 +0000 (11:43 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2016 19:43:32 +0000 (11:43 -0800)
"git reflog" incorrectly assumed that all objects that used to be
at the tip of a ref must be commits, which caused it to segfault.

* dk/reflog-walk-with-non-commit:
  reflog-walk: don't segfault on non-commit sha1's in the reflog

1  2 
reflog-walk.c

diff --combined reflog-walk.c
@@@ -56,11 -56,12 +56,11 @@@ static struct complete_reflogs *read_co
                }
        }
        if (reflogs->nr == 0) {
 -              int len = strlen(ref);
 -              char *refname = xmalloc(len + 12);
 -              sprintf(refname, "refs/%s", ref);
 +              char *refname = xstrfmt("refs/%s", ref);
                for_each_reflog_ent(refname, read_one_reflog, reflogs);
                if (reflogs->nr == 0) {
 -                      sprintf(refname, "refs/heads/%s", ref);
 +                      free(refname);
 +                      refname = xstrfmt("refs/heads/%s", ref);
                        for_each_reflog_ent(refname, read_one_reflog, reflogs);
                }
                free(refname);
@@@ -221,6 -222,7 +221,7 @@@ void fake_reflog_parent(struct reflog_w
        struct commit_info *commit_info =
                get_commit_info(commit, &info->reflogs, 0);
        struct commit_reflog *commit_reflog;
+       struct object *logobj;
        struct reflog_info *reflog;
  
        info->last_commit_reflog = NULL;
                commit->parents = NULL;
                return;
        }
-       reflog = &commit_reflog->reflogs->items[commit_reflog->recno];
        info->last_commit_reflog = commit_reflog;
-       commit_reflog->recno--;
-       commit_info->commit = (struct commit *)parse_object(reflog->osha1);
-       if (!commit_info->commit) {
+       do {
+               reflog = &commit_reflog->reflogs->items[commit_reflog->recno];
+               commit_reflog->recno--;
+               logobj = parse_object(reflog->osha1);
+       } while (commit_reflog->recno && (logobj && logobj->type != OBJ_COMMIT));
+       if (!logobj || logobj->type != OBJ_COMMIT) {
+               commit_info->commit = NULL;
                commit->parents = NULL;
                return;
        }
+       commit_info->commit = (struct commit *)logobj;
  
        commit->parents = xcalloc(1, sizeof(struct commit_list));
        commit->parents->item = commit_info->commit;