summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-01-25 19:41:59 +0100
committerLennart Poettering <lennart@poettering.net>2021-02-03 23:36:55 +0100
commit2ef2376d833dca05ab32bba41fcf5c345b25916e (patch)
treeece47cc3d30b7ab6b69159e9c3d4070d37986c49
parent0fb613000de5e3ae343778290bed0ff9e9f741e4 (diff)
downloadsystemd-2ef2376d833dca05ab32bba41fcf5c345b25916e.tar.gz
path-util: tighten path_is_valid() checks
This tightens the path_is_valid() checking: it now tests whether each component in the path is bound by FILENAME_MAX in its size.
-rw-r--r--src/basic/path-util.c23
-rw-r--r--src/test/test-path-util.c41
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();