Skip to content

Commit d2b86fb

Browse files
steadmongitster
authored andcommitted
commit-graph: fix buffer read-overflow
fuzz-commit-graph identified a case where Git will read past the end of a buffer containing a commit graph if the graph's header has an incorrect chunk count. A simple bounds check in parse_commit_graph() prevents this. Signed-off-by: Josh Steadmon <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent aa65857 commit d2b86fb

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

commit-graph.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,20 @@ struct commit_graph *parse_commit_graph(void *graph_map, int fd,
165165
last_chunk_offset = 8;
166166
chunk_lookup = data + 8;
167167
for (i = 0; i < graph->num_chunks; i++) {
168-
uint32_t chunk_id = get_be32(chunk_lookup + 0);
169-
uint64_t chunk_offset = get_be64(chunk_lookup + 4);
168+
uint32_t chunk_id;
169+
uint64_t chunk_offset;
170170
int chunk_repeated = 0;
171171

172+
if (data + graph_size - chunk_lookup <
173+
GRAPH_CHUNKLOOKUP_WIDTH) {
174+
error(_("chunk lookup table entry missing; graph file may be incomplete"));
175+
free(graph);
176+
return NULL;
177+
}
178+
179+
chunk_id = get_be32(chunk_lookup + 0);
180+
chunk_offset = get_be64(chunk_lookup + 4);
181+
172182
chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
173183

174184
if (chunk_offset > graph_size - GIT_MAX_RAWSZ) {

t/t5318-commit-graph.sh

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,21 +366,26 @@ GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
366366
GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
367367
GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES))
368368

369-
# usage: corrupt_graph_and_verify <position> <data> <string>
369+
# usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]
370370
# Manipulates the commit-graph file at the position
371-
# by inserting the data, then runs 'git commit-graph verify'
371+
# by inserting the data, optionally zeroing the file
372+
# starting at <zero_pos>, then runs 'git commit-graph verify'
372373
# and places the output in the file 'err'. Test 'err' for
373374
# the given string.
374375
corrupt_graph_and_verify() {
375376
pos=$1
376377
data="${2:-\0}"
377378
grepstr=$3
378379
cd "$TRASH_DIRECTORY/full" &&
380+
orig_size=$(wc -c < $objdir/info/commit-graph) &&
381+
zero_pos=${4:-${orig_size}} &&
379382
test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
380383
cp $objdir/info/commit-graph commit-graph-backup &&
381384
printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
385+
dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" count=0 &&
386+
dd if=/dev/zero of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" count=$(($orig_size - $zero_pos)) &&
382387
test_must_fail git commit-graph verify 2>test_err &&
383-
grep -v "^+" test_err >err
388+
grep -v "^+" test_err >err &&
384389
test_i18ngrep "$grepstr" err
385390
}
386391

@@ -484,6 +489,11 @@ test_expect_success 'detect invalid checksum hash' '
484489
"incorrect checksum"
485490
'
486491

492+
test_expect_success 'detect incorrect chunk count' '
493+
corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\377" \
494+
"chunk lookup table entry missing" $GRAPH_CHUNK_LOOKUP_OFFSET
495+
'
496+
487497
test_expect_success 'git fsck (checks commit-graph)' '
488498
cd "$TRASH_DIRECTORY/full" &&
489499
git fsck &&

0 commit comments

Comments
 (0)