diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-06-19 15:59:12 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-06-20 10:26:39 +0200 |
commit | f2981c2ff581e4e425c7b23da43aee29f25232c5 (patch) | |
tree | 5e809b9d7aff2db64edcd89afdf1ed4b40f054d5 | |
parent | 2f172ede7115d0a2730a3b689131042ba559e272 (diff) |
simplify and improve canonicalize_name
- Replace scan and memmove with simple automaton
- Convert forward to back slashes, lots of file systems treat them
equivalenty, this saves us a few more checks down the road
- Remove './' path components. We can saveley remove them in a string
processing step instead of throwing an error. Also they actually appear
often in tar balls, possibly not under user control.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | include/util.h | 6 | ||||
-rw-r--r-- | lib/util/canonicalize_name.c | 78 |
2 files changed, 41 insertions, 43 deletions
diff --git a/include/util.h b/include/util.h index 28d21bc..d5b20dd 100644 --- a/include/util.h +++ b/include/util.h @@ -6,9 +6,9 @@ #include <stdint.h> /* - Removes all preceeding and trailing slashes, shortens all sequences of - slashes to a single slash and returns failure state if one of the path - components is '..' or '.'. + Convert back to forward slashed, remove all preceeding and trailing slashes, + collapse all sequences of slashes, remove all path components that are '.' + and returns failure state if one of the path components is '..'. Returns 0 on success. */ diff --git a/lib/util/canonicalize_name.c b/lib/util/canonicalize_name.c index 6703b66..57e4d66 100644 --- a/lib/util/canonicalize_name.c +++ b/lib/util/canonicalize_name.c @@ -1,56 +1,54 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ -#include <string.h> - #include "util.h" -int canonicalize_name(char *filename) +static void normalize_slashes(char *filename) { - char *ptr = filename; - int i; - - while (*ptr == '/') - ++ptr; - - if (ptr != filename) { - memmove(filename, ptr, strlen(ptr) + 1); - ptr = filename; - } - - while (*ptr != '\0') { - if (*ptr == '/') { - for (i = 0; ptr[i] == '/'; ++i) - ; - - if (i > 1) - memmove(ptr + 1, ptr + i, strlen(ptr + i) + 1); - } - - if (ptr[0] == '/' && ptr[1] == '\0') { - *ptr = '\0'; - break; + char *dst = filename, *src = filename; + + while (*src == '/' || *src == '\\') + ++src; + + while (*src != '\0') { + if (*src == '/' || *src == '\\') { + while (*src == '/' || *src == '\\') + ++src; + if (*src == '\0') + break; + *(dst++) = '/'; + } else { + *(dst++) = *(src++); } - - ++ptr; } - ptr = filename; + *dst = '\0'; +} - while (*ptr != '\0') { - if (ptr[0] == '.') { - if (ptr[1] == '/' || ptr[1] == '\0') - return -1; +int canonicalize_name(char *filename) +{ + char *dst = filename, *src = filename; - if (ptr[1] == '.' && - (ptr[2] == '/' || ptr[2] == '\0')) { - return -1; + normalize_slashes(filename); + + while (*src != '\0') { + if (src[0] == '.') { + if (src[1] == '\0') + break; + if (src[1] == '/') { + src += 2; + continue; } + if (src[1] == '.' && (src[2] == '/' || src[2] == '\0')) + return -1; } - while (*ptr != '\0' && *ptr != '/') - ++ptr; - if (*ptr == '/') - ++ptr; + while (*src != '\0' && *src != '/') + *(dst++) = *(src++); + + if (*src == '/') + *(dst++) = *(src++); } + *dst = '\0'; + normalize_slashes(filename); return 0; } |