From: Christian Brauner Date: Tue, 30 Mar 2021 15:20:51 +0000 (+0200) Subject: string_utils: switch to path_simplify() X-Git-Tag: lxc-5.0.0~226^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F3756%2Fhead;p=thirdparty%2Flxc.git string_utils: switch to path_simplify() Link: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32689 Signed-off-by: Christian Brauner --- diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c index 4d52d044d..df25c031a 100644 --- a/src/lxc/confile_utils.c +++ b/src/lxc/confile_utils.c @@ -667,13 +667,13 @@ int set_config_string_item_max(char **conf_item, const char *value, size_t max) int set_config_path_item(char **conf_item, const char *value) { - __do_free char *normalized = NULL; + __do_free char *valdup = NULL; - normalized = lxc_deslashify(value); - if (!normalized) - return syserror_set(-ENOMEM, "Failed to normalize path config item"); + valdup = path_simplify(value); + if (!valdup) + return -ENOMEM; - return set_config_string_item_max(conf_item, normalized, PATH_MAX); + return set_config_string_item_max(conf_item, valdup, PATH_MAX); } int set_config_bool_item(bool *conf_item, const char *value, bool empty_conf_action) diff --git a/src/lxc/criu.c b/src/lxc/criu.c index c630bf741..c7e49b163 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -319,7 +319,7 @@ static int exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate limit cgroup path"); } - tmp = lxc_deslashify(cgroup_base_path); + tmp = path_simplify(cgroup_base_path); if (!tmp) return log_error_errno(-ENOMEM, ENOMEM, "Failed to remove extraneous slashes from \"%s\"", tmp); free_move_ptr(cgroup_base_path, tmp); diff --git a/src/lxc/storage/overlay.c b/src/lxc/storage/overlay.c index 770785cfd..5ff410e11 100644 --- a/src/lxc/storage/overlay.c +++ b/src/lxc/storage/overlay.c @@ -192,11 +192,11 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char * don't need to record a dependency. If we would restore would * also fail. */ - clean_old_path = lxc_deslashify(oldpath); + clean_old_path = path_simplify(oldpath); if (!clean_old_path) return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", oldpath); - clean_new_path = lxc_deslashify(lxcpath); + clean_new_path = path_simplify(lxcpath); if (!clean_new_path) return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", lxcpath); diff --git a/src/lxc/string_utils.c b/src/lxc/string_utils.c index 3312e6244..18c64c11e 100644 --- a/src/lxc/string_utils.c +++ b/src/lxc/string_utils.c @@ -195,7 +195,6 @@ char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix) char **lxc_normalize_path(const char *path) { char **components; - char **p; size_t components_len = 0; size_t pos = 0; @@ -203,9 +202,6 @@ char **lxc_normalize_path(const char *path) if (!components) return NULL; - for (p = components; *p; p++) - components_len++; - /* resolve '.' and '..' */ for (pos = 0; pos < components_len;) { if (strequal(components[pos], ".") || @@ -231,47 +227,58 @@ char **lxc_normalize_path(const char *path) return components; } -char *lxc_deslashify(const char *path) +/* taken from systemd */ +char *path_simplify(const char *path) { - char *dup, *p; - char **parts = NULL; - size_t n, len; + __do_free char *path_new = NULL; + char *f, *t; + bool slash = false, ignore_slash = false, absolute; - dup = strdup(path); - if (!dup) + path_new = strdup(path); + if (!path_new) return NULL; - parts = lxc_normalize_path(dup); - if (!parts) { - free(dup); - return NULL; + if (is_empty_string(path_new)) + return move_ptr(path_new); + + absolute = abspath(path_new); + + f = path_new; + if (*f == '.' && IN_SET(f[1], 0, '/')) { + ignore_slash = true; + f++; } - /* We'll end up here if path == "///" or path == "". */ - if (!*parts) { - len = strlen(dup); - if (!len) { - lxc_free_array((void **)parts, free); - return dup; - } + for (t = path_new; *f; f++) { - n = strcspn(dup, "/"); - if (n == len) { - free(dup); - lxc_free_array((void **)parts, free); + if (*f == '/') { + slash = true; + continue; + } - p = strdup("/"); - if (!p) - return NULL; + if (slash) { + if (*f == '.' && IN_SET(f[1], 0, '/')) + continue; - return p; + slash = false; + if (ignore_slash) + ignore_slash = false; + else + *(t++) = '/'; } + + *(t++) = *f; + } + + if (t == path_new) { + if (absolute) + *(t++) = '/'; + else + *(t++) = '.'; } - p = lxc_string_join("/", (const char **)parts, *dup == '/'); - free(dup); - lxc_free_array((void **)parts, free); - return p; + *t = 0; + return move_ptr(path_new); } char *lxc_append_paths(const char *first, const char *second) diff --git a/src/lxc/string_utils.h b/src/lxc/string_utils.h index 76c765d3c..1bea9a01c 100644 --- a/src/lxc/string_utils.h +++ b/src/lxc/string_utils.h @@ -196,4 +196,6 @@ static inline const char *fdstr(int fd) (__iterator = __it); \ __iterator = __it = strtok_r(NULL, __separators, &__p)) +__hidden extern char *path_simplify(const char *path); + #endif /* __LXC_STRING_UTILS_H */ diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c index 9b3e8cd19..3a26aecf3 100644 --- a/src/tests/lxc-test-utils.c +++ b/src/tests/lxc-test-utils.c @@ -43,12 +43,12 @@ #include "macro.h" #include "utils.h" -void test_lxc_deslashify(void) +void test_path_simplify(void) { char *s = "/A///B//C/D/E/"; char *t; - t = lxc_deslashify(s); + t = path_simplify(s); if (!t) exit(EXIT_FAILURE); @@ -57,7 +57,7 @@ void test_lxc_deslashify(void) s = "/A"; - t = lxc_deslashify(s); + t = path_simplify(s); if (!t) exit(EXIT_FAILURE); @@ -65,7 +65,7 @@ void test_lxc_deslashify(void) free(t); s = ""; - t = lxc_deslashify(s); + t = path_simplify(s); if (!t) exit(EXIT_FAILURE); @@ -74,7 +74,7 @@ void test_lxc_deslashify(void) s = "//"; - t = lxc_deslashify(s); + t = path_simplify(s); if (!t) exit(EXIT_FAILURE); @@ -598,7 +598,7 @@ int main(int argc, char *argv[]) { test_lxc_string_replace(); test_lxc_string_in_array(); - test_lxc_deslashify(); + test_path_simplify(); test_detect_ramfs_rootfs(); test_lxc_safe_uint(); test_lxc_safe_int();