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