fs_path: add long path validation on windows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
diff --git a/src/fs_path.c b/src/fs_path.c
index 483b21c..de3b039 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 275b3d8..40b4342 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 d54bc5b..a6b396f 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 {