summaryrefslogtreecommitdiff
path: root/reflog-walk.c
diff options
context:
space:
mode:
authorDennis Kaarsemaker <dennis@kaarsemaker.net>2016-01-05 22:12:10 +0100
committerJunio C Hamano <gitster@pobox.com>2016-01-05 13:41:06 -0800
commitaecad374ae7492cc7b2add5fa416d43e1f68c18e (patch)
tree0803b378a4b228e46f6e8c83730590ac345dc694 /reflog-walk.c
parent1ff88560c8d22bcdb528a6629239d638f927cb96 (diff)
downloadgit-aecad374ae7492cc7b2add5fa416d43e1f68c18e.tar.gz
reflog-walk: don't segfault on non-commit sha1's in the reflogdk/reflog-walk-with-non-commit
git reflog (ab)uses the log machinery to display its list of log entries. To do so it must fake commit parent information for the log walker. For refs in refs/heads this is no problem, as they should only ever point to commits. Tags and other refs however can point to anything, thus their reflog may contain non-commit objects. To avoid segfaulting, we check whether reflog entries are commits before feeding them to the log walker and skip any non-commits. This means that git reflog output will be incomplete for such refs, but that's one step up from segfaulting. A more complete solution would be to decouple git reflog from the log walker machinery. Signed-off-by: Dennis Kaarsemaker <dennis@kaarsemaker.net> Helped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'reflog-walk.c')
-rw-r--r--reflog-walk.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/reflog-walk.c b/reflog-walk.c
index f8e743a23b..d3cc5240f3 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -222,6 +222,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
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;
@@ -233,15 +234,20 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
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;