git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 09/12] sparse-checkout: properly match escaped characters

From
Derrick Stolee <stolee@gmail.com>
Date
Jan 29, 2020, 13:58 UTC
Message-ID
<6003bbf2-ad16-0686-dc58-2010fe02ce05@gmail.com>
In-Reply-To
<20200129100309.GA4218@coredump.intra.peff.net>
On 1/29/2020 5:03 AM, Jeff King wrote:
Show 10 quoted lines
> On Tue, Jan 28, 2020 at 06:26:40PM +0000, Derrick Stolee via GitGitGadget wrote:
> 
>> From: Derrick Stolee <dstolee@microsoft.com>
>>
>> In cone mode, the sparse-checkout feature uses hashset containment
>> queries to match paths. Make this algorithm respect escaped asterisk
>> (*) and backslash (\) characters.
> 
> Do we also need to worry about other glob metacharacters? E.g., "?" or
> ranges like "[A-Z]"?
These are not part of the .gitignore patterns [1].
[1] https://git-scm.com/docs/gitignore#_pattern_format
Show 29 quoted lines
>> +static char *dup_and_filter_pattern(const char *pattern)
>> +{
>> +	char *set, *read;
>> +	char *result = xstrdup(pattern);
>> +
>> +	set = result;
>> +	read = result;
>> +
>> +	while (*read) {
>> +		/* skip escape characters (once) */
>> +		if (*read == '\\')
>> +			read++;
>> +
>> +		*set = *read;
>> +
>> +		set++;
>> +		read++;
>> +	}
>> +	*set = 0;
>> +
>> +	if (*(read - 2) == '/' && *(read - 1) == '*')
>> +		*(read - 2) = 0;
>> +
>> +	return result;
>> +}
> 
> Do we need to check that the pattern is longer than 1 character here? If
> it's a single character, it seems like this "*(read - 2)" will
> dereference the byte before the string.

This method is only called by add_pattern_to_hashsets(), which has a guard against paths of length less than 2, but thats' no excuse for dangerous pointer arithmetic here.

But you also point out an even more confusing thing: why are we modifying based on the 'read' pointer, and not the 'set' pointer? This seems to work _accidentally_ only when the pattern has "<something>/*" and "<something>" has no escape characters.

I had to recall exactly why we are dropping this "/*", but it's because the pattern _actually_ ends with "/*/" but the in-memory pattern has already dropped that last slash and applied PATTERN_FLAG_MUSTBEDIR.

Here is a diff that I can apply to this patch to fix this problem _and_ demonstrate it in the tests:

diff --git a/dir.c b/dir.c
index 579f274d13..277577c8bf 100644
--- a/dir.c
+++ b/dir.c
@@ -633,6 +633,7 @@ int pl_hashmap_cmp(const void *unused_cmp_data,
 static char *dup_and_filter_pattern(const char *pattern)
 {
        char *set, *read;
+       size_t count  = 0;
        char *result = xstrdup(pattern);
 
        set = result;
@@ -647,11 +648,14 @@ static char *dup_and_filter_pattern(const char *pattern)
 
                set++;
                read++;
+               count++;
        }
        *set = 0;
 
-       if (*(read - 2) == '/' && *(read - 1) == '*')
-               *(read - 2) = 0;
+       if (count > 2 &&
+           *(set - 1) == '*' &&
+           *(set - 2) == '/')
+               *(set - 2) = 0;
 
        return result;
 }
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 0a21a5e15d..20b0465f77 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -383,6 +383,7 @@ test_expect_success BSLASHPSPEC 'pattern-checks: escaped "*"' '
        /*
        !/*/
        /zbad\\dir/
+       !/zbad\\dir/*/
        /zdoes\*not\*exist/
        /zdoes\*exist/
        EOF

With this extra line in the test, but compiling the old version of this patch,
the test fails with:

'err' is not empty, it contains:
+ cat err
warning: unrecognized negative pattern: '/zbad\\dir/*'
warning: disabling cone pattern matching

To ensure this negative pattern exists in the later patch where we set
the patterns using the builtin, I'll add "zbad\\dir/bogus" to the list
of directories to include, which will add another pattern to the set.

Thanks,
-Stolee
Previous: Jeff KingNext: Derrick Stolee
Message 61 of 82 in “Harden the sparse-checkout builtin”
  1. 0/8 Harden the sparse-checkout builtinDerrick Stolee via GitGitGadget, Jan 14, 2020
  2. 2/8 sparse-checkout: create leading directoriesDerrick Stolee via GitGitGadget, Jan 14, 2020
  3. Junio C HamanoJan 16, 2020
  4. 1/8 t1091: use check_files to reduce boilerplateDerrick Stolee via GitGitGadget, Jan 14, 2020
  5. Junio C HamanoJan 16, 2020
  6. 4/8 sparse-checkout: cone mode does not recognize "**"Derrick Stolee via GitGitGadget, Jan 14, 2020
  7. Jeff KingJan 14, 2020
  8. 5/8 sparse-checkout: detect short patternsDerrick Stolee via GitGitGadget, Jan 14, 2020
  9. 3/8 clone: fix --sparse option with URLsDerrick Stolee via GitGitGadget, Jan 14, 2020
  10. Taylor BlauJan 14, 2020
  11. 7/8 sparse-checkout: properly match escaped charactersDerrick Stolee via GitGitGadget, Jan 14, 2020
  12. Jeff KingJan 14, 2020
  13. Derrick StoleeJan 14, 2020
  14. 6/8 sparse-checkout: warn on incorrect '*' in patternsDerrick Stolee via GitGitGadget, Jan 14, 2020
  15. 8/8 sparse-checkout: write escaped patterns in cone modeDerrick Stolee via GitGitGadget, Jan 14, 2020
  16. Jeff KingJan 14, 2020
  17. Derrick StoleeJan 14, 2020
  18. Jeff KingJan 14, 2020
  19. Derrick StoleeJan 24, 2020
  20. Jeff KingJan 24, 2020
  21. Derrick StoleeJan 28, 2020
  22. Taylor BlauJan 14, 2020
  23. Derrick StoleeJan 14, 2020
  24. Jeff KingJan 14, 2020
  25. Junio C HamanoJan 15, 2020
  26. Derrick StoleeJan 15, 2020
  27. 00/12 Harden the sparse-checkout builtinDerrick Stolee via GitGitGadget, Jan 24, 2020
  28. 01/12 t1091: use check_files to reduce boilerplateDerrick Stolee via GitGitGadget, Jan 24, 2020
  29. 02/12 t1091: improve here-docsDerrick Stolee via GitGitGadget, Jan 24, 2020
  30. 04/12 clone: fix --sparse option with URLsDerrick Stolee via GitGitGadget, Jan 24, 2020
  31. 05/12 sparse-checkout: fix documentation typo for core.sparseCheckoutConeJeff King via GitGitGadget, Jan 24, 2020
  32. 06/12 sparse-checkout: cone mode does not recognize "**"Derrick Stolee via GitGitGadget, Jan 24, 2020
  33. 03/12 sparse-checkout: create leading directoriesDerrick Stolee via GitGitGadget, Jan 24, 2020
  34. 09/12 sparse-checkout: properly match escaped charactersDerrick Stolee via GitGitGadget, Jan 24, 2020
  35. 08/12 sparse-checkout: warn on incorrect '*' in patternsDerrick Stolee via GitGitGadget, Jan 24, 2020
  36. 07/12 sparse-checkout: detect short patternsDerrick Stolee via GitGitGadget, Jan 24, 2020
  37. 12/12 sparse-checkout: improve docs around 'set' in cone modeDerrick Stolee via GitGitGadget, Jan 24, 2020
  38. 10/12 sparse-checkout: write escaped patterns in cone modeDerrick Stolee via GitGitGadget, Jan 24, 2020
  39. 11/12 sparse-checkout: use C-style quotes in 'list' subcommandDerrick Stolee via GitGitGadget, Jan 24, 2020
  40. 00/12 Harden the sparse-checkout builtinDerrick Stolee via GitGitGadget, Jan 28, 2020
  41. 01/12 t1091: use check_files to reduce boilerplateDerrick Stolee via GitGitGadget, Jan 28, 2020
  42. 02/12 t1091: improve here-docsDerrick Stolee via GitGitGadget, Jan 28, 2020
  43. 04/12 clone: fix --sparse option with URLsDerrick Stolee via GitGitGadget, Jan 28, 2020
  44. 05/12 sparse-checkout: fix documentation typo for core.sparseCheckoutConeJeff King via GitGitGadget, Jan 28, 2020
  45. 03/12 sparse-checkout: create leading directoriesDerrick Stolee via GitGitGadget, Jan 28, 2020
  46. 06/12 sparse-checkout: cone mode does not recognize "**"Derrick Stolee via GitGitGadget, Jan 28, 2020
  47. 11/12 sparse-checkout: use C-style quotes in 'list' subcommandDerrick Stolee via GitGitGadget, Jan 28, 2020
  48. Jeff KingJan 29, 2020
  49. 12/12 sparse-checkout: improve docs around 'set' in cone modeDerrick Stolee via GitGitGadget, Jan 28, 2020
  50. 10/12 sparse-checkout: write escaped patterns in cone modeDerrick Stolee via GitGitGadget, Jan 28, 2020
  51. Jeff KingJan 29, 2020
  52. Jeff KingJan 29, 2020
  53. Derrick StoleeJan 29, 2020
  54. Derrick StoleeJan 29, 2020
  55. Jeff KingJan 30, 2020
  56. Derrick StoleeJan 30, 2020
  57. 08/12 sparse-checkout: warn on incorrect '*' in patternsDerrick Stolee via GitGitGadget, Jan 28, 2020
  58. 07/12 sparse-checkout: detect short patternsDerrick Stolee via GitGitGadget, Jan 28, 2020
  59. 09/12 sparse-checkout: properly match escaped charactersDerrick Stolee via GitGitGadget, Jan 28, 2020
  60. Jeff KingJan 29, 2020
  61. Derrick StoleeJan 29, 2020
  62. Derrick StoleeJan 29, 2020
  63. 00/15 Harden the sparse-checkout builtinDerrick Stolee via GitGitGadget, Jan 31, 2020
  64. 01/15 t1091: use check_files to reduce boilerplateDerrick Stolee via GitGitGadget, Jan 31, 2020
  65. 02/15 t1091: improve here-docsDerrick Stolee via GitGitGadget, Jan 31, 2020
  66. 04/15 clone: fix --sparse option with URLsDerrick Stolee via GitGitGadget, Jan 31, 2020
  67. 06/15 sparse-checkout: cone mode does not recognize "**"Derrick Stolee via GitGitGadget, Jan 31, 2020
  68. 07/15 sparse-checkout: detect short patternsDerrick Stolee via GitGitGadget, Jan 31, 2020
  69. 05/15 sparse-checkout: fix documentation typo for core.sparseCheckoutConeJeff King via GitGitGadget, Jan 31, 2020
  70. 08/15 sparse-checkout: warn on globs in cone patternsDerrick Stolee via GitGitGadget, Jan 31, 2020
  71. 03/15 sparse-checkout: create leading directoriesDerrick Stolee via GitGitGadget, Jan 31, 2020
  72. 09/15 sparse-checkout: properly match escaped charactersDerrick Stolee via GitGitGadget, Jan 31, 2020
  73. 11/15 sparse-checkout: unquote C-style strings over --stdinDerrick Stolee via GitGitGadget, Jan 31, 2020
  74. 10/15 sparse-checkout: write escaped patterns in cone modeDerrick Stolee via GitGitGadget, Jan 31, 2020
  75. 15/15 sparse-checkout: fix cone mode behavior mismatchDerrick Stolee via GitGitGadget, Jan 31, 2020
  76. 14/15 sparse-checkout: improve docs around 'set' in cone modeDerrick Stolee via GitGitGadget, Jan 31, 2020
  77. 12/15 sparse-checkout: use C-style quotes in 'list' subcommandDerrick Stolee via GitGitGadget, Jan 31, 2020
  78. 13/15 sparse-checkout: escape all glob characters on writeDerrick Stolee via GitGitGadget, Jan 31, 2020
  79. Elijah NewrenJan 31, 2020
  80. Derrick StoleeFeb 3, 2020
  81. Taylor BlauFeb 8, 2020
  82. Junio C HamanoFeb 9, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.