diff options
-rw-r--r-- | src/basic/path-util.c | 23 | ||||
-rw-r--r-- | src/test/test-path-util.c | 41 |
2 files changed, 55 insertions, 9 deletions
diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 3dff09b151..f7498d0125 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -891,7 +891,7 @@ bool filename_is_valid(const char *p) { if (*e != 0) return false; - if (e - p > FILENAME_MAX) /* FILENAME_MAX is counted *without* the trailing NUL byte */ + if (e - p > NAME_MAX) /* NAME_MAX is counted *without* the trailing NUL byte */ return false; return true; @@ -902,10 +902,25 @@ bool path_is_valid(const char *p) { if (isempty(p)) return false; - if (strlen(p) >= PATH_MAX) /* PATH_MAX is counted *with* the trailing NUL byte */ - return false; + for (const char *e = p;;) { + size_t n; - return true; + /* Skip over slashes */ + e += strspn(e, "/"); + if (e - p >= PATH_MAX) /* Already reached the maximum length for a path? (PATH_MAX is counted + * *with* the trailing NUL byte) */ + return false; + if (*e == 0) /* End of string? Yay! */ + return true; + + /* Skip over one component */ + n = strcspn(e, "/"); + if (n > NAME_MAX) /* One component larger than NAME_MAX? (NAME_MAX is counted *without* the + * trailing NUL byte) */ + return false; + + e += n; + } } bool path_is_normalized(const char *p) { diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 206f5fd436..58b185494d 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -604,8 +604,7 @@ static void test_path_extract_filename(void) { } static void test_filename_is_valid(void) { - char foo[FILENAME_MAX+2]; - int i; + char foo[NAME_MAX+2]; log_info("/* %s */", __func__); @@ -618,9 +617,8 @@ static void test_filename_is_valid(void) { assert_se(!filename_is_valid("bar/foo/")); assert_se(!filename_is_valid("bar//")); - for (i=0; i<FILENAME_MAX+1; i++) - foo[i] = 'a'; - foo[FILENAME_MAX+1] = '\0'; + memset(foo, 'a', sizeof(foo) - 1); + char_array_0(foo); assert_se(!filename_is_valid(foo)); @@ -628,6 +626,38 @@ static void test_filename_is_valid(void) { assert_se(filename_is_valid("o.o")); } +static void test_path_is_valid(void) { + char foo[PATH_MAX+2]; + const char *c; + + log_info("/* %s */", __func__); + + assert_se(!path_is_valid("")); + assert_se(path_is_valid("/bar/foo")); + assert_se(path_is_valid("/bar/foo/")); + assert_se(path_is_valid("/bar/foo/")); + assert_se(path_is_valid("//bar//foo//")); + assert_se(path_is_valid("/")); + assert_se(path_is_valid("/////")); + assert_se(path_is_valid("/////.///.////...///..//.")); + assert_se(path_is_valid(".")); + assert_se(path_is_valid("..")); + assert_se(path_is_valid("bar/foo")); + assert_se(path_is_valid("bar/foo/")); + assert_se(path_is_valid("bar//")); + + memset(foo, 'a', sizeof(foo) -1); + char_array_0(foo); + + assert_se(!path_is_valid(foo)); + + c = strjoina("/xxx/", foo, "/yyy"); + assert_se(!path_is_valid(c)); + + assert_se(path_is_valid("foo_bar-333")); + assert_se(path_is_valid("o.o")); +} + static void test_hidden_or_backup_file(void) { log_info("/* %s */", __func__); @@ -761,6 +791,7 @@ int main(int argc, char **argv) { test_last_path_component(); test_path_extract_filename(); test_filename_is_valid(); + test_path_is_valid(); test_hidden_or_backup_file(); test_skip_dev_prefix(); test_empty_or_root(); |