Skip to content

Commit ebacd24

Browse files
committed
fs_path: add long path validation on windows
1 parent dd748db commit ebacd24

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

src/fs_path.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,11 +1634,25 @@ static bool validate_component(
16341634
return true;
16351635
}
16361636

1637+
#ifdef GIT_WIN32
1638+
GIT_INLINE(bool) validate_length(
1639+
const char *path,
1640+
size_t len,
1641+
size_t utf8_char_len)
1642+
{
1643+
GIT_UNUSED(path);
1644+
GIT_UNUSED(len);
1645+
1646+
return (utf8_char_len <= MAX_PATH);
1647+
}
1648+
#endif
1649+
16371650
bool git_fs_path_is_valid_str_ext(
16381651
const git_str *path,
16391652
unsigned int flags,
16401653
bool (*validate_char_cb)(char ch, void *payload),
16411654
bool (*validate_component_cb)(const char *component, size_t len, void *payload),
1655+
bool (*validate_length_cb)(const char *path, size_t len, size_t utf8_char_len),
16421656
void *payload)
16431657
{
16441658
const char *start, *c;
@@ -1683,6 +1697,21 @@ bool git_fs_path_is_valid_str_ext(
16831697
!validate_component_cb(start, (c - start), payload))
16841698
return false;
16851699

1700+
#ifdef GIT_WIN32
1701+
if ((flags & GIT_FS_PATH_REJECT_LONG_PATHS) != 0) {
1702+
size_t utf8_len = git_utf8_char_length(path->ptr, len);
1703+
1704+
if (!validate_length(path->ptr, len, utf8_len))
1705+
return false;
1706+
1707+
if (validate_length_cb &&
1708+
!validate_length_cb(path->ptr, len, utf8_len))
1709+
return false;
1710+
}
1711+
#else
1712+
GIT_UNUSED(validate_length_cb);
1713+
#endif
1714+
16861715
return true;
16871716
}
16881717

src/fs_path.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -600,8 +600,9 @@ extern int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url
600600
#define GIT_FS_PATH_REJECT_TRAILING_COLON (1 << 6)
601601
#define GIT_FS_PATH_REJECT_DOS_PATHS (1 << 7)
602602
#define GIT_FS_PATH_REJECT_NT_CHARS (1 << 8)
603+
#define GIT_FS_PATH_REJECT_LONG_PATHS (1 << 9)
603604

604-
#define GIT_FS_PATH_REJECT_MAX (1 << 8)
605+
#define GIT_FS_PATH_REJECT_MAX (1 << 9)
605606

606607
/* Default path safety for writing files to disk: since we use the
607608
* Win32 "File Namespace" APIs ("\\?\") we need to protect from
@@ -632,13 +633,15 @@ extern bool git_fs_path_is_valid_str_ext(
632633
unsigned int flags,
633634
bool (*validate_char_cb)(char ch, void *payload),
634635
bool (*validate_component_cb)(const char *component, size_t len, void *payload),
636+
bool (*validate_length_cb)(const char *component, size_t len, size_t utf8_char_len),
635637
void *payload);
636638

637639
GIT_INLINE(bool) git_fs_path_is_valid_ext(
638640
const char *path,
639641
unsigned int flags,
640642
bool (*validate_char_cb)(char ch, void *payload),
641643
bool (*validate_component_cb)(const char *component, size_t len, void *payload),
644+
bool (*validate_length_cb)(const char *component, size_t len, size_t utf8_char_len),
642645
void *payload)
643646
{
644647
const git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX);
@@ -647,6 +650,7 @@ GIT_INLINE(bool) git_fs_path_is_valid_ext(
647650
flags,
648651
validate_char_cb,
649652
validate_component_cb,
653+
validate_length_cb,
650654
payload);
651655
}
652656

@@ -662,15 +666,15 @@ GIT_INLINE(bool) git_fs_path_is_valid(
662666
unsigned int flags)
663667
{
664668
const git_str str = GIT_STR_INIT_CONST(path, SIZE_MAX);
665-
return git_fs_path_is_valid_str_ext(&str, flags, NULL, NULL, NULL);
669+
return git_fs_path_is_valid_str_ext(&str, flags, NULL, NULL, NULL, NULL);
666670
}
667671

668672
/** Validate a filesystem path in a `git_str`. */
669673
GIT_INLINE(bool) git_fs_path_is_valid_str(
670674
const git_str *path,
671675
unsigned int flags)
672676
{
673-
return git_fs_path_is_valid_str_ext(path, flags, NULL, NULL, NULL);
677+
return git_fs_path_is_valid_str_ext(path, flags, NULL, NULL, NULL, NULL);
674678
}
675679

676680
/**

src/path.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ bool git_path_is_valid(
301301
data.file_mode = file_mode;
302302
data.flags = flags;
303303

304-
return git_fs_path_is_valid_ext(path, flags, NULL, validate_repo_component, &data);
304+
return git_fs_path_is_valid_ext(path, flags, NULL, validate_repo_component, NULL, &data);
305305
}
306306

307307
static const struct {

0 commit comments

Comments
 (0)