Skip to content

Commit 9ee9954

Browse files
committed
commit-graph: use timestamp_t for max parent generation accumulator
compute_reachable_generation_numbers() computes each commit's generation as max(c->date, max(parent.generation)) + 1 by walking its parents and accumulating their generations into a local uint32_t max_gen = 0; while info->get_generation() returns timestamp_t and compute_generation_from_max() already takes its max_gen parameter as timestamp_t. For v1 (topological levels) the narrowing is harmless because GENERATION_NUMBER_V1_MAX is less than 2^30, but for v2 (corrected committer dates) it silently truncates any parent generation that does not fit in 32 bits, i.e. any parent whose committer timestamp is at or beyond 2106-02-07 UTC (>= 2^32). The truncated max then loses its dominance over c->date and the child commit ends up with a generation that violates v2 monotonicity. The bad value gets written into the GDA2 chunk and is caught later by `git commit-graph verify`. Widen the accumulator to timestamp_t. The narrowing was introduced in 6f6ecca307a7 (commit-graph: combine generation computations, 2022-04-04), when the v1 and v2 generation computations were unified into a single helper. The existing "single commit with generation data exceeding UINT32_MAX" test in t5328 covers a root commit, which has no parents whose generation could overflow the accumulator. Add a test with a future-dated parent and a present-day child; without this fix `git commit-graph verify` reports the descendant's stored generation as below parent + 1. Signed-off-by: Elijah Newren <newren@gmail.com>
1 parent 600fe74 commit 9ee9954

2 files changed

Lines changed: 10 additions & 1 deletion

File tree

commit-graph.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1669,7 +1669,7 @@ static void compute_reachable_generation_numbers(
16691669
struct commit *current = list->item;
16701670
struct commit_list *parent;
16711671
int all_parents_computed = 1;
1672-
uint32_t max_gen = 0;
1672+
timestamp_t max_gen = 0;
16731673

16741674
for (parent = current->parents; parent; parent = parent->next) {
16751675
repo_parse_commit(info->r, parent->item);

t/t5328-commit-graph-64bit-time.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ test_expect_success 'single commit with generation data exceeding UINT32_MAX' '
7474
git -C repo-uint32-max commit-graph verify
7575
'
7676

77+
test_expect_success 'descendant of commit with date exceeding UINT32_MAX' '
78+
git init repo-uint32-max-descendant &&
79+
test_commit -C repo-uint32-max-descendant \
80+
--date "@4294967300 +0000" future-parent &&
81+
test_commit -C repo-uint32-max-descendant present-day-child &&
82+
git -C repo-uint32-max-descendant commit-graph write --reachable &&
83+
git -C repo-uint32-max-descendant commit-graph verify
84+
'
85+
7786
test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds generation overflow' '
7887
graph=.git/objects/info/commit-graph &&
7988
test_when_finished "rm -rf $graph" &&

0 commit comments

Comments
 (0)