diff options
author | Lennart Poettering <lennart@poettering.net> | 2017-10-02 10:51:19 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2017-10-02 17:41:44 +0200 |
commit | 2a5beb669f62299bfa2543765d3edf8885f9eb55 (patch) | |
tree | 8c6c192fd1fafa60c40c414c41e3666a098697ea /src/basic/path-util.c | |
parent | 091e9efed3f417bdd8bdee814d8676757ffb19db (diff) | |
download | systemd-2a5beb669f62299bfa2543765d3edf8885f9eb55.tar.gz |
path-util: some updates to path_make_relative()
Don't miscount number of "../" to generate, if we "." is included in an
input path.
Also, refuse if we encounter "../" since we can't possibly follow that
up properly, without file system access.
Some other modernizations.
Diffstat (limited to 'src/basic/path-util.c')
-rw-r--r-- | src/basic/path-util.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 80fdda170f..6c06bd2acb 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -131,8 +131,7 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) { /* Skip the common part. */ for (;;) { - size_t a; - size_t b; + size_t a, b; from_dir += strspn(from_dir, "/"); to_path += strspn(to_path, "/"); @@ -144,7 +143,6 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) { else /* from_dir is a parent directory of to_path. */ r = strdup(to_path); - if (!r) return -ENOMEM; @@ -175,21 +173,32 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) { /* Count the number of necessary ".." elements. */ for (n_parents = 0;;) { + size_t w; + from_dir += strspn(from_dir, "/"); if (!*from_dir) break; - from_dir += strcspn(from_dir, "/"); - n_parents++; + w = strcspn(from_dir, "/"); + + /* If this includes ".." we can't do a simple series of "..", refuse */ + if (w == 2 && from_dir[0] == '.' && from_dir[1] == '.') + return -EINVAL; + + /* Count number of elements, except if they are "." */ + if (w != 1 || from_dir[0] != '.') + n_parents++; + + from_dir += w; } - r = malloc(n_parents * 3 + strlen(to_path) + 1); + r = new(char, n_parents * 3 + strlen(to_path) + 1); if (!r) return -ENOMEM; - for (p = r; n_parents > 0; n_parents--, p += 3) - memcpy(p, "../", 3); + for (p = r; n_parents > 0; n_parents--) + p = mempcpy(p, "../", 3); strcpy(p, to_path); path_kill_slashes(r); |