Skip to content

Commit 8f41c07

Browse files
René Scharfegitster
authored andcommitted
read-cache.c: fix index memory allocation
estimate_cache_size() tries to guess how much memory is needed for the in-memory representation of an index file. It does that by using the file size, the number of entries and the difference of the sizes of the on-disk and in-memory structs -- without having to check the length of the name of each entry, which varies for each entry, but their sums are the same no matter the representation. Except there can be a difference. First of all, the size is really calculated by ce_size and ondisk_ce_size based on offsetof(..., name), not sizeof, which can be different. And entries are padded with 1 to 8 NULs at the end (after the variable name) to make their total length a multiple of eight. So in order to allocate enough memory to hold the index, change the delta calculation to be based on offsetof(..., name) and round up to the next multiple of eight. On a 32-bit Linux, this delta was used before: sizeof(struct cache_entry) == 72 sizeof(struct ondisk_cache_entry) == 64 --- 8 The actual difference for an entry with a filename length of one was, however (find the definitions are in cache.h): offsetof(struct cache_entry, name) == 72 offsetof(struct ondisk_cache_entry, name) == 62 ce_size == (72 + 1 + 8) & ~7 == 80 ondisk_ce_size == (62 + 1 + 8) & ~7 == 64 --- 16 So eight bytes less had been allocated for such entries. The new formula yields the correct delta: (72 - 62 + 7) & ~7 == 16 Reported-by: John Hsing <[email protected]> Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f7d958d commit 8f41c07

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

read-cache.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,9 +1249,9 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
12491249

12501250
static inline size_t estimate_cache_size(size_t ondisk_size, unsigned int entries)
12511251
{
1252-
long per_entry;
1253-
1254-
per_entry = sizeof(struct cache_entry) - sizeof(struct ondisk_cache_entry);
1252+
size_t fix_size_mem = offsetof(struct cache_entry, name);
1253+
size_t fix_size_dsk = offsetof(struct ondisk_cache_entry, name);
1254+
long per_entry = (fix_size_mem - fix_size_dsk + 7) & ~7;
12551255

12561256
/*
12571257
* Alignment can cause differences. This should be "alignof", but

t/t7511-status-index.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/sh
2+
3+
test_description='git status with certain file name lengths'
4+
5+
. ./test-lib.sh
6+
7+
files="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
8+
9+
check() {
10+
len=$1
11+
prefix=$2
12+
13+
for i in $files
14+
do
15+
: >$prefix$i
16+
done
17+
18+
test_expect_success "status, filename length $len" "
19+
git add $prefix* &&
20+
git status
21+
"
22+
rm $prefix* .git/index
23+
}
24+
25+
check 1
26+
check 2 p
27+
check 3 pr
28+
check 4 pre
29+
check 5 pref
30+
check 6 prefi
31+
check 7 prefix
32+
check 8 prefix-
33+
check 9 prefix-p
34+
check 10 prefix-pr
35+
check 11 prefix-pre
36+
check 12 prefix-pref
37+
check 13 prefix-prefi
38+
check 14 prefix-prefix
39+
check 15 prefix-prefix-
40+
check 16 prefix-prefix-p
41+
check 17 prefix-prefix-pr
42+
check 18 prefix-prefix-pre
43+
check 19 prefix-prefix-pref
44+
check 20 prefix-prefix-prefi
45+
check 21 prefix-prefix-prefix
46+
check 22 prefix-prefix-prefix-
47+
check 23 prefix-prefix-prefix-p
48+
check 24 prefix-prefix-prefix-pr
49+
50+
test_done

0 commit comments

Comments
 (0)