Skip to content

Commit de6a414

Browse files
brandb97gitster
authored andcommitted
pack-bitmap: add load corrupt bitmap test
This patch add test_bitmap_list_commits_offset() in patch-bitmap.c, a new test helper command `test-tool bitmap list-commits-offset`, and a `load corrupt bitmap` test case in t5310. The `load corrupt bitmap` test case intentionally corrupt the "xor_offset" field of the first entry. And the newly added helper can help to find position of "xor_offset" in bitmap file. Signed-off-by: Lidong Yan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 118f665 commit de6a414

File tree

4 files changed

+96
-5
lines changed

4 files changed

+96
-5
lines changed

pack-bitmap.c

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct stored_bitmap {
3131
struct object_id oid;
3232
struct ewah_bitmap *root;
3333
struct stored_bitmap *xor;
34+
size_t map_pos;
3435
int flags;
3536
};
3637

@@ -314,13 +315,14 @@ static struct stored_bitmap *store_bitmap(struct bitmap_index *index,
314315
struct ewah_bitmap *root,
315316
const struct object_id *oid,
316317
struct stored_bitmap *xor_with,
317-
int flags)
318+
int flags, size_t map_pos)
318319
{
319320
struct stored_bitmap *stored;
320321
khiter_t hash_pos;
321322
int ret;
322323

323324
stored = xmalloc(sizeof(struct stored_bitmap));
325+
stored->map_pos = map_pos;
324326
stored->root = root;
325327
stored->xor = xor_with;
326328
stored->flags = flags;
@@ -376,10 +378,12 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
376378
struct stored_bitmap *xor_bitmap = NULL;
377379
uint32_t commit_idx_pos;
378380
struct object_id oid;
381+
size_t entry_map_pos;
379382

380383
if (index->map_size - index->map_pos < 6)
381384
return error(_("corrupt ewah bitmap: truncated header for entry %d"), i);
382385

386+
entry_map_pos = index->map_pos;
383387
commit_idx_pos = read_be32(index->map, &index->map_pos);
384388
xor_offset = read_u8(index->map, &index->map_pos);
385389
flags = read_u8(index->map, &index->map_pos);
@@ -402,8 +406,9 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
402406
if (!bitmap)
403407
return -1;
404408

405-
recent_bitmaps[i % MAX_XOR_OFFSET] = store_bitmap(
406-
index, bitmap, &oid, xor_bitmap, flags);
409+
recent_bitmaps[i % MAX_XOR_OFFSET] =
410+
store_bitmap(index, bitmap, &oid, xor_bitmap, flags,
411+
entry_map_pos);
407412
}
408413

409414
return 0;
@@ -869,6 +874,7 @@ static struct stored_bitmap *lazy_bitmap_for_commit(struct bitmap_index *bitmap_
869874
int xor_flags;
870875
khiter_t hash_pos;
871876
struct bitmap_lookup_table_xor_item *xor_item;
877+
size_t entry_map_pos;
872878

873879
if (is_corrupt)
874880
return NULL;
@@ -928,14 +934,16 @@ static struct stored_bitmap *lazy_bitmap_for_commit(struct bitmap_index *bitmap_
928934
goto corrupt;
929935
}
930936

937+
entry_map_pos = bitmap_git->map_pos;
931938
bitmap_git->map_pos += sizeof(uint32_t) + sizeof(uint8_t);
932939
xor_flags = read_u8(bitmap_git->map, &bitmap_git->map_pos);
933940
bitmap = read_bitmap_1(bitmap_git);
934941

935942
if (!bitmap)
936943
goto corrupt;
937944

938-
xor_bitmap = store_bitmap(bitmap_git, bitmap, &xor_item->oid, xor_bitmap, xor_flags);
945+
xor_bitmap = store_bitmap(bitmap_git, bitmap, &xor_item->oid,
946+
xor_bitmap, xor_flags, entry_map_pos);
939947
xor_items_nr--;
940948
}
941949

@@ -969,14 +977,16 @@ static struct stored_bitmap *lazy_bitmap_for_commit(struct bitmap_index *bitmap_
969977
* Instead, we can skip ahead and immediately read the flags and
970978
* ewah bitmap.
971979
*/
980+
entry_map_pos = bitmap_git->map_pos;
972981
bitmap_git->map_pos += sizeof(uint32_t) + sizeof(uint8_t);
973982
flags = read_u8(bitmap_git->map, &bitmap_git->map_pos);
974983
bitmap = read_bitmap_1(bitmap_git);
975984

976985
if (!bitmap)
977986
goto corrupt;
978987

979-
return store_bitmap(bitmap_git, bitmap, oid, xor_bitmap, flags);
988+
return store_bitmap(bitmap_git, bitmap, oid, xor_bitmap, flags,
989+
entry_map_pos);
980990

981991
corrupt:
982992
free(xor_items);
@@ -2857,6 +2867,48 @@ int test_bitmap_commits(struct repository *r)
28572867
return 0;
28582868
}
28592869

2870+
int test_bitmap_commits_with_offset(struct repository *r)
2871+
{
2872+
struct object_id oid;
2873+
struct stored_bitmap *stored;
2874+
struct bitmap_index *bitmap_git;
2875+
size_t commit_idx_pos_map_pos, xor_offset_map_pos, flag_map_pos,
2876+
ewah_bitmap_map_pos;
2877+
2878+
bitmap_git = prepare_bitmap_git(r);
2879+
if (!bitmap_git)
2880+
die(_("failed to load bitmap indexes"));
2881+
2882+
/*
2883+
* Since this function needs to know the position of each individual
2884+
* bitmap, bypass the commit lookup table (if one exists) by forcing
2885+
* the bitmap to eagerly load its entries.
2886+
*/
2887+
if (bitmap_git->table_lookup) {
2888+
if (load_bitmap_entries_v1(bitmap_git) < 0)
2889+
die(_("failed to load bitmap indexes"));
2890+
}
2891+
2892+
kh_foreach (bitmap_git->bitmaps, oid, stored, {
2893+
commit_idx_pos_map_pos = stored->map_pos;
2894+
xor_offset_map_pos = stored->map_pos + sizeof(uint32_t);
2895+
flag_map_pos = xor_offset_map_pos + sizeof(uint8_t);
2896+
ewah_bitmap_map_pos = flag_map_pos + sizeof(uint8_t);
2897+
2898+
printf_ln("%s %"PRIuMAX" %"PRIuMAX" %"PRIuMAX" %"PRIuMAX,
2899+
oid_to_hex(&oid),
2900+
(uintmax_t)commit_idx_pos_map_pos,
2901+
(uintmax_t)xor_offset_map_pos,
2902+
(uintmax_t)flag_map_pos,
2903+
(uintmax_t)ewah_bitmap_map_pos);
2904+
})
2905+
;
2906+
2907+
free_bitmap_index(bitmap_git);
2908+
2909+
return 0;
2910+
}
2911+
28602912
int test_bitmap_hashes(struct repository *r)
28612913
{
28622914
struct bitmap_index *bitmap_git = prepare_bitmap_git(r);

pack-bitmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ void traverse_bitmap_commit_list(struct bitmap_index *,
8181
show_reachable_fn show_reachable);
8282
void test_bitmap_walk(struct rev_info *revs);
8383
int test_bitmap_commits(struct repository *r);
84+
int test_bitmap_commits_with_offset(struct repository *r);
8485
int test_bitmap_hashes(struct repository *r);
8586
int test_bitmap_pseudo_merges(struct repository *r);
8687
int test_bitmap_pseudo_merge_commits(struct repository *r, uint32_t n);

t/helper/test-bitmap.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ static int bitmap_list_commits(void)
1010
return test_bitmap_commits(the_repository);
1111
}
1212

13+
static int bitmap_list_commits_with_offset(void)
14+
{
15+
return test_bitmap_commits_with_offset(the_repository);
16+
}
17+
1318
static int bitmap_dump_hashes(void)
1419
{
1520
return test_bitmap_hashes(the_repository);
@@ -36,6 +41,8 @@ int cmd__bitmap(int argc, const char **argv)
3641

3742
if (argc == 2 && !strcmp(argv[1], "list-commits"))
3843
return bitmap_list_commits();
44+
if (argc == 2 && !strcmp(argv[1], "list-commits-with-offset"))
45+
return bitmap_list_commits_with_offset();
3946
if (argc == 2 && !strcmp(argv[1], "dump-hashes"))
4047
return bitmap_dump_hashes();
4148
if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges"))
@@ -46,6 +53,7 @@ int cmd__bitmap(int argc, const char **argv)
4653
return bitmap_dump_pseudo_merge_objects(atoi(argv[2]));
4754

4855
usage("\ttest-tool bitmap list-commits\n"
56+
"\ttest-tool bitmap list-commits-with-offset\n"
4957
"\ttest-tool bitmap dump-hashes\n"
5058
"\ttest-tool bitmap dump-pseudo-merges\n"
5159
"\ttest-tool bitmap dump-pseudo-merge-commits <n>\n"

t/t5310-pack-bitmaps.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,36 @@ test_bitmap_cases () {
486486
grep "ignoring extra bitmap" trace2.txt
487487
)
488488
'
489+
490+
test_expect_success 'load corrupt bitmap' '
491+
rm -fr repo &&
492+
git init repo &&
493+
test_when_finished "rm -fr repo" &&
494+
(
495+
cd repo &&
496+
git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
497+
498+
test_commit base &&
499+
500+
git repack -adb &&
501+
bitmap="$(ls .git/objects/pack/pack-*.bitmap)" &&
502+
chmod +w $bitmap &&
503+
504+
test-tool bitmap list-commits-with-offset >offsets &&
505+
xor_off=$(head -n1 offsets | awk "{print \$3}") &&
506+
printf '\161' |
507+
dd of=$bitmap count=1 bs=1 conv=notrunc seek=$xor_off &&
508+
509+
git rev-list --objects --no-object-names HEAD >expect.raw &&
510+
git rev-list --objects --use-bitmap-index --no-object-names HEAD \
511+
>actual.raw &&
512+
513+
sort expect.raw >expect &&
514+
sort actual.raw >actual &&
515+
516+
test_cmp expect actual
517+
)
518+
'
489519
}
490520

491521
test_bitmap_cases

0 commit comments

Comments
 (0)