| From faacb80440afdc737669dcc88bbac0d4c49240d0 Mon Sep 17 00:00:00 2001 |
| From: Jeff King <peff@peff.net> |
| Date: Wed, 2 May 2018 15:23:45 -0400 |
| Subject: is_hfs_dotgit: match other .git files |
| |
| commit 0fc333ba20b43a8afee5023e92cb3384ff4e59a6 upstream. |
| |
| Both verify_path() and fsck match ".git", ".GIT", and other |
| variants specific to HFS+. Let's allow matching other |
| special files like ".gitmodules", which we'll later use to |
| enforce extra restrictions via verify_path() and fsck. |
| |
| Signed-off-by: Jeff King <peff@peff.net> |
| Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> |
| --- |
| utf8.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++------------ |
| utf8.h | 5 +++++ |
| 2 files changed, 51 insertions(+), 12 deletions(-) |
| |
| diff --git a/utf8.c b/utf8.c |
| index 00e10c86ad..0d406b12de 100644 |
| --- a/utf8.c |
| +++ b/utf8.c |
| @@ -605,28 +605,33 @@ static ucs_char_t next_hfs_char(const char **in) |
| } |
| } |
| |
| -int is_hfs_dotgit(const char *path) |
| +static int is_hfs_dot_generic(const char *path, |
| + const char *needle, size_t needle_len) |
| { |
| ucs_char_t c; |
| |
| c = next_hfs_char(&path); |
| if (c != '.') |
| return 0; |
| - c = next_hfs_char(&path); |
| |
| /* |
| * there's a great deal of other case-folding that occurs |
| - * in HFS+, but this is enough to catch anything that will |
| - * convert to ".git" |
| + * in HFS+, but this is enough to catch our fairly vanilla |
| + * hard-coded needles. |
| */ |
| - if (c != 'g' && c != 'G') |
| - return 0; |
| - c = next_hfs_char(&path); |
| - if (c != 'i' && c != 'I') |
| - return 0; |
| - c = next_hfs_char(&path); |
| - if (c != 't' && c != 'T') |
| - return 0; |
| + for (; needle_len > 0; needle++, needle_len--) { |
| + c = next_hfs_char(&path); |
| + |
| + /* |
| + * We know our needles contain only ASCII, so we clamp here to |
| + * make the results of tolower() sane. |
| + */ |
| + if (c > 127) |
| + return 0; |
| + if (tolower(c) != *needle) |
| + return 0; |
| + } |
| + |
| c = next_hfs_char(&path); |
| if (c && !is_dir_sep(c)) |
| return 0; |
| @@ -634,6 +639,35 @@ int is_hfs_dotgit(const char *path) |
| return 1; |
| } |
| |
| +/* |
| + * Inline wrapper to make sure the compiler resolves strlen() on literals at |
| + * compile time. |
| + */ |
| +static inline int is_hfs_dot_str(const char *path, const char *needle) |
| +{ |
| + return is_hfs_dot_generic(path, needle, strlen(needle)); |
| +} |
| + |
| +int is_hfs_dotgit(const char *path) |
| +{ |
| + return is_hfs_dot_str(path, "git"); |
| +} |
| + |
| +int is_hfs_dotgitmodules(const char *path) |
| +{ |
| + return is_hfs_dot_str(path, "gitmodules"); |
| +} |
| + |
| +int is_hfs_dotgitignore(const char *path) |
| +{ |
| + return is_hfs_dot_str(path, "gitignore"); |
| +} |
| + |
| +int is_hfs_dotgitattributes(const char *path) |
| +{ |
| + return is_hfs_dot_str(path, "gitattributes"); |
| +} |
| + |
| const char utf8_bom[] = "\357\273\277"; |
| |
| int skip_utf8_bom(char **text, size_t len) |
| diff --git a/utf8.h b/utf8.h |
| index 6bbcf31a83..da19b43114 100644 |
| --- a/utf8.h |
| +++ b/utf8.h |
| @@ -52,8 +52,13 @@ int mbs_chrlen(const char **text, size_t *remainder_p, const char *encoding); |
| * The path should be NUL-terminated, but we will match variants of both ".git\0" |
| * and ".git/..." (but _not_ ".../.git"). This makes it suitable for both fsck |
| * and verify_path(). |
| + * |
| + * Likewise, the is_hfs_dotgitfoo() variants look for ".gitfoo". |
| */ |
| int is_hfs_dotgit(const char *path); |
| +int is_hfs_dotgitmodules(const char *path); |
| +int is_hfs_dotgitignore(const char *path); |
| +int is_hfs_dotgitattributes(const char *path); |
| |
| typedef enum { |
| ALIGN_LEFT, |
| -- |
| 2.17.0.921.gf22659ad46 |
| |