diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-11-01 13:58:18 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2021-11-09 15:17:18 +0000 |
commit | ebacd24c6039c992ef9122a0d6f7de0ca4ba3bd1 (patch) | |
tree | b3e8e91bc2d0fa0a61ba88d57c7ff783eeb5ab25 | |
parent | dd748dbede1a36f1e929461ecbfcde749eb685bb (diff) | |
download | libgit2-ebacd24c6039c992ef9122a0d6f7de0ca4ba3bd1.tar.gz |
fs_path: add long path validation on windows
-rw-r--r-- | src/fs_path.c | 29 | ||||
-rw-r--r-- | src/fs_path.h | 10 | ||||
-rw-r--r-- | src/path.c | 2 |
3 files changed, 37 insertions, 4 deletions
diff --git a/src/fs_path.c b/src/fs_path.c index 483b21c1e..de3b03957 100644 --- a/src/fs_path.c +++ b/src/fs_path.c @@ -1634,11 +1634,25 @@ static bool validate_component( return true; } +#ifdef GIT_WIN32 +GIT_INLINE(bool) validate_length( + const char *path, + size_t len, + size_t utf8_char_len) +{ + GIT_UNUSED(path); + GIT_UNUSED(len); + + return (utf8_char_len <= MAX_PATH); +} +#endif + bool git_fs_path_is_valid_str_ext( const git_str *path, unsigned int flags, bool (*validate_char_cb)(char ch, void *payload), bool (*validate_component_cb)(const char *component, size_t len, void *payload), + bool (*validate_length_cb)(const char *path, size_t len, size_t utf8_char_len), void *payload) { const char *start, *c; @@ -1683,6 +1697,21 @@ bool git_fs_path_is_valid_str_ext( !validate_component_cb(start, (c - start), payload)) return false; +#ifdef GIT_WIN32 + if ((flags & GIT_FS_PATH_REJECT_LONG_PATHS) != 0) { + size_t utf8_len = git_utf8_char_length(path->ptr, len); + + if (!validate_length(path->ptr, len, utf8_len)) + return false; + + if (validate_length_cb && + !validate_length_cb(path->ptr, len, utf8_len)) + return false; + } +#else + GIT_UNUSED(validate_length_cb); +#endif + return true; } diff --git a/src/fs_path.h b/src/fs_path.h index 275b3d857..40b4342f1 100644 --- a/src/fs_path.h +++ b/src/fs_path.h @@ -600,8 +600,9 @@ extern int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url #define GIT_FS_PATH_REJECT_TRAILING_COLON (1 << 6) #define GIT_FS_PATH_REJECT_DOS_PATHS (1 << 7) #define GIT_FS_PATH_REJECT_NT_CHARS (1 << 8) +#define GIT_FS_PATH_REJECT_LONG_PATHS (1 << 9) -#define GIT_FS_PATH_REJECT_MAX (1 << 8) +#define GIT_FS_PATH_REJECT_MAX (1 << 9) /* Default path safety for writing files to disk: since we use the * Win32 "File Namespace" APIs ("\\?\") we need to protect from @@ -632,6 +633,7 @@ extern bool git_fs_path_is_valid_str_ext( unsigned int flags, bool (*validate_char_cb)(char ch, void *payload), bool (*validate_component_cb)(const char *component, size_t len, void *payload), + bool (*validate_length_cb)(const char *component, size_t len, size_t utf8_char_len), void *payload); GIT_INLINE(bool) git_fs_path_is_valid_ext( @@ -639,6 +641,7 @@ GIT_INLINE(bool) git_fs_path_is_valid_ext( unsigned int flags, bool (*validate_char_cb)(char ch, void *payload), bool (*validate_component_cb)(const char *component, size_t len, void *payload), + bool (*validate_length_cb)(const char *component, size_t len, size_t utf8_char_len), void *payload) { const git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX); @@ -647,6 +650,7 @@ GIT_INLINE(bool) git_fs_path_is_valid_ext( flags, validate_char_cb, validate_component_cb, + validate_length_cb, payload); } @@ -662,7 +666,7 @@ GIT_INLINE(bool) git_fs_path_is_valid( unsigned int flags) { const git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX); - return git_fs_path_is_valid_str_ext(&str, flags, NULL, NULL, NULL); + return git_fs_path_is_valid_str_ext(&str, flags, NULL, NULL, NULL, NULL); } /** Validate a filesystem path in a `git_str`. */ @@ -670,7 +674,7 @@ GIT_INLINE(bool) git_fs_path_is_valid_str( const git_str *path, unsigned int flags) { - return git_fs_path_is_valid_str_ext(path, flags, NULL, NULL, NULL); + return git_fs_path_is_valid_str_ext(path, flags, NULL, NULL, NULL, NULL); } /** diff --git a/src/path.c b/src/path.c index d54bc5bfe..a6b396f6d 100644 --- a/src/path.c +++ b/src/path.c @@ -301,7 +301,7 @@ bool git_path_is_valid( data.file_mode = file_mode; data.flags = flags; - return git_fs_path_is_valid_ext(path, flags, NULL, validate_repo_component, &data); + return git_fs_path_is_valid_ext(path, flags, NULL, validate_repo_component, NULL, &data); } static const struct { |