1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-11 05:17:44 +03:00

path-util: use path_find_first_component() in path_startswith()

This makes path_startswith() stricter. If one of the path component in
arguments is longer than NAME_MAX, it returns NULL.
This commit is contained in:
Yu Watanabe 2021-05-01 20:17:16 +09:00
parent 0b8696256b
commit 63f11e354a
3 changed files with 49 additions and 56 deletions

View File

@ -430,7 +430,7 @@ int path_simplify_and_warn(
return 0;
}
char* path_startswith(const char *path, const char *prefix) {
char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) {
assert(path);
assert(prefix);
@ -448,28 +448,25 @@ char* path_startswith(const char *path, const char *prefix) {
return NULL;
for (;;) {
size_t a, b;
const char *p, *q;
int r, k;
path += strspn(path, "/");
prefix += strspn(prefix, "/");
if (*prefix == 0)
return (char*) path;
if (*path == 0)
r = path_find_first_component(&path, accept_dot_dot, &p);
if (r < 0)
return NULL;
a = strcspn(path, "/");
b = strcspn(prefix, "/");
if (a != b)
k = path_find_first_component(&prefix, accept_dot_dot, &q);
if (k < 0)
return NULL;
if (memcmp(path, prefix, a) != 0)
if (k == 0)
return (char*) (p ?: path);
if (r != k)
return NULL;
path += a;
prefix += b;
if (!strneq(p, q, r))
return NULL;
}
}

View File

@ -57,7 +57,10 @@ char* path_make_absolute(const char *p, const char *prefix);
int safe_getcwd(char **ret);
int path_make_absolute_cwd(const char *p, char **ret);
int path_make_relative(const char *from_dir, const char *to_path, char **_r);
char* path_startswith(const char *path, const char *prefix) _pure_;
char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) _pure_;
static inline char* path_startswith(const char *path, const char *prefix) {
return path_startswith_full(path, prefix, true);
}
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b, int flags);

View File

@ -473,49 +473,42 @@ static void test_strv_resolve(void) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
static void test_path_startswith(void) {
const char *p;
static void test_path_startswith_one(const char *path, const char *prefix, const char *skipped, const char *expected) {
const char *p, *q;
log_debug("/* %s(%s, %s) */", __func__, path, prefix);
p = path_startswith(path, prefix);
assert_se(streq_ptr(p, expected));
if (p) {
q = strjoina(skipped, p);
assert_se(streq(q, path));
assert_se(p == path + strlen(skipped));
}
}
static void test_path_startswith(void) {
log_info("/* %s */", __func__);
p = path_startswith("/foo/bar/barfoo/", "/foo");
assert_se(streq_ptr(p, "bar/barfoo/"));
test_path_startswith_one("/foo/bar/barfoo/", "/foo", "/foo/", "bar/barfoo/");
test_path_startswith_one("/foo/bar/barfoo/", "/foo/", "/foo/", "bar/barfoo/");
test_path_startswith_one("/foo/bar/barfoo/", "/", "/", "foo/bar/barfoo/");
test_path_startswith_one("/foo/bar/barfoo/", "////", "/", "foo/bar/barfoo/");
test_path_startswith_one("/foo/bar/barfoo/", "/foo//bar/////barfoo///", "/foo/bar/barfoo/", "");
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfoo////", "/foo/bar/barfoo/", "");
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar///barfoo/", "/foo/bar/barfoo/", "");
test_path_startswith_one("/foo/bar/barfoo/", "/foo////bar/barfoo/", "/foo/bar/barfoo/", "");
test_path_startswith_one("/foo/bar/barfoo/", "////foo/bar/barfoo/", "/foo/bar/barfoo/", "");
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfoo", "/foo/bar/barfoo/", "");
p = path_startswith("/foo/bar/barfoo/", "/foo/");
assert_se(streq_ptr(p, "bar/barfoo/"));
p = path_startswith("/foo/bar/barfoo/", "/");
assert_se(streq_ptr(p, "foo/bar/barfoo/"));
p = path_startswith("/foo/bar/barfoo/", "////");
assert_se(streq_ptr(p, "foo/bar/barfoo/"));
p = path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///");
assert_se(streq_ptr(p, ""));
p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////");
assert_se(streq_ptr(p, ""));
p = path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/");
assert_se(streq_ptr(p, ""));
p = path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/");
assert_se(streq_ptr(p, ""));
p = path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/");
assert_se(streq_ptr(p, ""));
p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo");
assert_se(streq_ptr(p, ""));
assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/"));
assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa"));
assert_se(!path_startswith("/foo/bar/barfoo/", ""));
assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo"));
assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/"));
assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfo"));
assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/bar"));
assert_se(!path_startswith("/foo/bar/barfoo/", "/fo"));
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfooa/", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfooa", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "/bar/foo", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "/f/b/b/", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfo", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/bar", NULL, NULL);
test_path_startswith_one("/foo/bar/barfoo/", "/fo", NULL, NULL);
}
static void test_prefix_root_one(const char *r, const char *p, const char *expected) {