cache_name_compare(): do not truncate while comparing paths
We failed to use ce_namelen() equivalent and instead only compared up to the CE_NAMEMASK bytes by mistake. Adding an overlong path that shares the same common prefix as an existing entry in the index did not add a new entry, but instead replaced the existing one, as the result. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Jul 11, 2012 at 09:08 UTC
d5f53338ab2ee29c588f46d5cb28d7e3b25018f2
2 files changed
+48
-4
read-cache.c
+9
-4
@@ -405,10 +405,15 @@ int df_name_compare(const char *name1, int len1, int mode1,
405
406
int cache_name_compare(const char *name1, int flags1, const char *name2, int flags2)
407
{
408
- int len1 = flags1 & CE_NAMEMASK;
409
- int len2 = flags2 & CE_NAMEMASK;
410
- int len = len1 < len2 ? len1 : len2;
411
- int cmp;
408
+ int len1, len2, len, cmp;
409
+
410
+ len1 = flags1 & CE_NAMEMASK;
411
+ if (CE_NAMEMASK <= len1)
412
+ len1 = strlen(name1 + CE_NAMEMASK) + CE_NAMEMASK;
413
+ len2 = flags2 & CE_NAMEMASK;
414
+ if (CE_NAMEMASK <= len2)
415
+ len2 = strlen(name2 + CE_NAMEMASK) + CE_NAMEMASK;
416
+ len = len1 < len2 ? len1 : len2;
417
418
cmp = memcmp(name1, name2, len);
419
if (cmp)
t/t3006-ls-files-long.sh
new
+39
@@ -0,0 +1,39 @@
1
+#!/bin/sh
2
+
3
+test_description='overly long paths'
4
+. ./test-lib.sh
5
+
6
+test_expect_success setup '
7
+ p=filefilefilefilefilefilefilefile &&
8
+ p=$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p &&
9
+ p=$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p &&
10
+
11
+ path_a=${p}_a &&
12
+ path_z=${p}_z &&
13
+
14
+ blob_a=$(echo frotz | git hash-object -w --stdin) &&
15
+ blob_z=$(echo nitfol | git hash-object -w --stdin) &&
16
+
17
+ pat="100644 %s 0\t%s\n"
18
+'
19
+
20
+test_expect_success 'overly-long path by itself is not a problem' '
21
+ printf "$pat" "$blob_a" "$path_a" |
22
+ git update-index --add --index-info &&
23
+ echo "$path_a" >expect &&
24
+ git ls-files >actual &&
25
+ test_cmp expect actual
26
+'
27
+
28
+test_expect_success 'overly-long path does not replace another by mistake' '
29
+ printf "$pat" "$blob_a" "$path_a" "$blob_z" "$path_z" |
30
+ git update-index --add --index-info &&
31
+ (
32
+ echo "$path_a"
33
+ echo "$path_z"
34
+ ) >expect &&
35
+ git ls-files >actual &&
36
+ test_cmp expect actual
37
+'
38
+
39
+test_done