summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-11-01 13:04:40 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2021-11-09 15:17:17 +0000
commitdd748dbede1a36f1e929461ecbfcde749eb685bb (patch)
tree60e695e05378a21db5218c81285a5c0e3b5de395
parentbef02d3e638ce8c95c9e63622b46d87a0f8ee2b2 (diff)
downloadlibgit2-dd748dbede1a36f1e929461ecbfcde749eb685bb.tar.gz
fs_path: make empty component validation optional
-rw-r--r--src/fs_path.c5
-rw-r--r--src/fs_path.h5
-rw-r--r--tests/path/core.c43
3 files changed, 38 insertions, 15 deletions
diff --git a/src/fs_path.c b/src/fs_path.c
index fa27a6e73..483b21c1e 100644
--- a/src/fs_path.c
+++ b/src/fs_path.c
@@ -1599,7 +1599,7 @@ static bool validate_component(
unsigned int flags)
{
if (len == 0)
- return false;
+ return !(flags & GIT_FS_PATH_REJECT_EMPTY_COMPONENT);
if ((flags & GIT_FS_PATH_REJECT_TRAVERSAL) &&
len == 1 && component[0] == '.')
@@ -1644,6 +1644,9 @@ bool git_fs_path_is_valid_str_ext(
const char *start, *c;
size_t len = 0;
+ if (!flags)
+ return true;
+
for (start = c = path->ptr; *c && len < path->size; c++, len++) {
if (!validate_char(*c, flags))
return false;
diff --git a/src/fs_path.h b/src/fs_path.h
index 2f4bc9f79..275b3d857 100644
--- a/src/fs_path.h
+++ b/src/fs_path.h
@@ -591,7 +591,8 @@ extern bool git_fs_path_is_local_file_url(const char *file_url);
extern int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url_or_path);
/* Flags to determine path validity in `git_fs_path_isvalid` */
-#define GIT_FS_PATH_REJECT_TRAVERSAL (1 << 0)
+#define GIT_FS_PATH_REJECT_EMPTY_COMPONENT (1 << 0)
+#define GIT_FS_PATH_REJECT_TRAVERSAL (1 << 1)
#define GIT_FS_PATH_REJECT_SLASH (1 << 2)
#define GIT_FS_PATH_REJECT_BACKSLASH (1 << 3)
#define GIT_FS_PATH_REJECT_TRAILING_DOT (1 << 4)
@@ -608,6 +609,7 @@ extern int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url
*/
#ifdef GIT_WIN32
# define GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS \
+ GIT_FS_PATH_REJECT_EMPTY_COMPONENT | \
GIT_FS_PATH_REJECT_TRAVERSAL | \
GIT_FS_PATH_REJECT_BACKSLASH | \
GIT_FS_PATH_REJECT_TRAILING_DOT | \
@@ -617,6 +619,7 @@ extern int git_fs_path_from_url_or_path(git_str *local_path_out, const char *url
GIT_FS_PATH_REJECT_NT_CHARS
#else
# define GIT_FS_PATH_REJECT_FILESYSTEM_DEFAULTS \
+ GIT_FS_PATH_REJECT_EMPTY_COMPONENT | \
GIT_FS_PATH_REJECT_TRAVERSAL
#endif
diff --git a/tests/path/core.c b/tests/path/core.c
index 6fa0450ca..ccb328b10 100644
--- a/tests/path/core.c
+++ b/tests/path/core.c
@@ -68,41 +68,58 @@ void test_path_core__isvalid_standard(void)
void test_path_core__isvalid_standard_str(void)
{
git_str str = GIT_STR_INIT_CONST("foo/bar//zap", 0);
+ unsigned int flags = GIT_FS_PATH_REJECT_EMPTY_COMPONENT;
str.size = 0;
- cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, flags));
str.size = 3;
- cl_assert_equal_b(true, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(true, git_fs_path_is_valid_str(&str, flags));
str.size = 4;
- cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, flags));
str.size = 5;
- cl_assert_equal_b(true, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(true, git_fs_path_is_valid_str(&str, flags));
str.size = 7;
- cl_assert_equal_b(true, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(true, git_fs_path_is_valid_str(&str, flags));
str.size = 8;
- cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, flags));
str.size = strlen(str.ptr);
- cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, 0));
+ cl_assert_equal_b(false, git_fs_path_is_valid_str(&str, flags));
}
void test_path_core__isvalid_empty_dir_component(void)
{
- cl_assert_equal_b(false, git_fs_path_is_valid("foo//bar", 0));
+ unsigned int flags = GIT_FS_PATH_REJECT_EMPTY_COMPONENT;
+
+ /* empty component */
+ cl_assert_equal_b(true, git_fs_path_is_valid("foo//bar", 0));
+
+ /* leading slash */
+ cl_assert_equal_b(true, git_fs_path_is_valid("/", 0));
+ cl_assert_equal_b(true, git_fs_path_is_valid("/foo", 0));
+ cl_assert_equal_b(true, git_fs_path_is_valid("/foo/bar", 0));
+
+ /* trailing slash */
+ cl_assert_equal_b(true, git_fs_path_is_valid("foo/", 0));
+ cl_assert_equal_b(true, git_fs_path_is_valid("foo/bar/", 0));
+
+
+ /* empty component */
+ cl_assert_equal_b(false, git_fs_path_is_valid("foo//bar", flags));
/* leading slash */
- cl_assert_equal_b(false, git_fs_path_is_valid("/", 0));
- cl_assert_equal_b(false, git_fs_path_is_valid("/foo", 0));
- cl_assert_equal_b(false, git_fs_path_is_valid("/foo/bar", 0));
+ cl_assert_equal_b(false, git_fs_path_is_valid("/", flags));
+ cl_assert_equal_b(false, git_fs_path_is_valid("/foo", flags));
+ cl_assert_equal_b(false, git_fs_path_is_valid("/foo/bar", flags));
/* trailing slash */
- cl_assert_equal_b(false, git_fs_path_is_valid("foo/", 0));
- cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar/", 0));
+ cl_assert_equal_b(false, git_fs_path_is_valid("foo/", flags));
+ cl_assert_equal_b(false, git_fs_path_is_valid("foo/bar/", flags));
}
void test_path_core__isvalid_dot_and_dotdot(void)