log_tree_diff: die when we fail to parse a commit

We currently call parse_commit and then assume we can dereference the resulting "tree" struct field. If parsing failed, however, that field is NULL and we end up segfaulting. Instead of a segfault, let's print an error message and die a little more gracefully. Note that this should never happen in practice, but may happen in a corrupt repository. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Oct 24, 2013 at 04:52 UTC 7059dccc6c60a872a314b19ac17702065a71d6bd
3 files changed +11 -3
commit.c
+7
@@ -341,6 +341,13 @@ int parse_commit(struct commit *item)
341 return ret;
342 }
343
344 +void parse_commit_or_die(struct commit *item)
345 +{
346 + if (parse_commit(item))
347 + die("unable to parse commit %s",
348 + item ? sha1_to_hex(item->object.sha1) : "(null)");
349 +}
350 +
351 int find_commit_subject(const char *commit_buffer, const char **subject)
352 {
353 const char *eol;
commit.h
+1
@@ -49,6 +49,7 @@ struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_n
49
50 int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
51 int parse_commit(struct commit *item);
52 +void parse_commit_or_die(struct commit *item);
53
54 /* Find beginning and length of commit subject. */
55 int find_commit_subject(const char *commit_buffer, const char **subject);
log-tree.c
+3 -3
@@ -734,7 +734,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
734 if (!opt->diff && !DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS))
735 return 0;
736
737 - parse_commit(commit);
737 + parse_commit_or_die(commit);
738 sha1 = commit->tree->object.sha1;
739
740 /* Root commit? */
@@ -759,7 +759,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
759 * parent, showing summary diff of the others
760 * we merged _in_.
761 */
762 - parse_commit(parents->item);
762 + parse_commit_or_die(parents->item);
763 diff_tree_sha1(parents->item->tree->object.sha1,
764 sha1, "", &opt->diffopt);
765 log_tree_diff_flush(opt);
@@ -774,7 +774,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
774 for (;;) {
775 struct commit *parent = parents->item;
776
777 - parse_commit(parent);
777 + parse_commit_or_die(parent);
778 diff_tree_sha1(parent->tree->object.sha1,
779 sha1, "", &opt->diffopt);
780 log_tree_diff_flush(opt);