From 63f11e354a3e5d64ee4cabb7bb584307d237fee4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 1 May 2021 20:17:16 +0900 Subject: [PATCH] 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. --- src/basic/path-util.c | 27 +++++++-------- src/basic/path-util.h | 5 ++- src/test/test-path-util.c | 71 ++++++++++++++++++--------------------- 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 4b83232df88..aa65e2950fb 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -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; - - path += strspn(path, "/"); - prefix += strspn(prefix, "/"); + const char *p, *q; + int r, k; - if (*prefix == 0) - return (char*) path; + r = path_find_first_component(&path, accept_dot_dot, &p); + if (r < 0) + return NULL; - if (*path == 0) + k = path_find_first_component(&prefix, accept_dot_dot, &q); + if (k < 0) return NULL; - a = strcspn(path, "/"); - b = strcspn(prefix, "/"); + if (k == 0) + return (char*) (p ?: path); - if (a != b) + if (r != k) return NULL; - if (memcmp(path, prefix, a) != 0) + if (!strneq(p, q, r)) return NULL; - - path += a; - prefix += b; } } diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 52ceb9b5a95..50a7b021a49 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -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); diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index c68603fc9ba..49a547422e6 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -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; - - log_info("/* %s */", __func__); - - p = path_startswith("/foo/bar/barfoo/", "/foo"); - assert_se(streq_ptr(p, "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/")); +static void test_path_startswith_one(const char *path, const char *prefix, const char *skipped, const char *expected) { + const char *p, *q; - p = path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///"); - assert_se(streq_ptr(p, "")); + log_debug("/* %s(%s, %s) */", __func__, path, prefix); - 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(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)); + } +} - p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo"); - assert_se(streq_ptr(p, "")); +static void test_path_startswith(void) { + log_info("/* %s */", __func__); - 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", "/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/", ""); + + 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) { -- 2.47.3