diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-12-29 12:10:46 +0100 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-12-29 12:10:46 +0100 |
commit | 0e3bb2104a8e3fd07e201e6ba99f8d017fdc72a8 (patch) | |
tree | 1a494a001339a86f418c4dc96be85202c457ee25 | |
parent | 06a8c73c53a78c84d736ee7176522ed21a501ab4 (diff) |
Fix normalization of slashes in filenames
All paths were canonicalized internally, which includes filtering
sequences of slashes and converting backslashes to slashes.
Furthermore, when unpacking files, filenames are sanity checked
and rejected if they contain forward OR backward slashes.
This is a problem on Unix-like systems, where files containing
backslashes are a legitimate use case (*cough* SystemD *cough*).
This patch removes the backslash conversion from the canonicalization
and modifies the sanity check to reject backslashes only on Windows.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | lib/fstree/canonicalize_name.c | 6 | ||||
-rw-r--r-- | lib/fstree/filename_sane.c | 4 | ||||
-rw-r--r-- | tests/canonicalize_name.c | 10 | ||||
-rw-r--r-- | tests/filename_sane.c | 7 |
4 files changed, 14 insertions, 13 deletions
diff --git a/lib/fstree/canonicalize_name.c b/lib/fstree/canonicalize_name.c index f35307f..7fbd5a7 100644 --- a/lib/fstree/canonicalize_name.c +++ b/lib/fstree/canonicalize_name.c @@ -11,12 +11,12 @@ static void normalize_slashes(char *filename) { char *dst = filename, *src = filename; - while (*src == '/' || *src == '\\') + while (*src == '/') ++src; while (*src != '\0') { - if (*src == '/' || *src == '\\') { - while (*src == '/' || *src == '\\') + if (*src == '/') { + while (*src == '/') ++src; if (*src == '\0') break; diff --git a/lib/fstree/filename_sane.c b/lib/fstree/filename_sane.c index b0f8c90..91c15da 100644 --- a/lib/fstree/filename_sane.c +++ b/lib/fstree/filename_sane.c @@ -57,7 +57,7 @@ bool is_filename_sane(const char *name, bool check_os_specific) return false; while (*name != '\0') { - if (*name == '/' || *name == '\\') + if (*name == '/') return false; #if defined(_WIN32) || defined(__WINDOWS__) || defined(TEST_WIN32) @@ -66,7 +66,7 @@ bool is_filename_sane(const char *name, bool check_os_specific) return false; if (*name == '"' || *name == '|' || *name == '?') return false; - if (*name == '*' || *name <= 31) + if (*name == '*' || *name == '\\' || *name <= 31) return false; } #endif diff --git a/tests/canonicalize_name.c b/tests/canonicalize_name.c index 679cd06..2ab73a0 100644 --- a/tests/canonicalize_name.c +++ b/tests/canonicalize_name.c @@ -14,14 +14,14 @@ static const struct { } must_work[] = { { "", "" }, { "/", "" }, - { "\\", "" }, + { "\\", "\\" }, { "///", "" }, - { "\\\\\\", "" }, - { "/\\//\\\\/", "" }, + { "\\\\\\", "\\\\\\" }, + { "/\\//\\\\/", "\\/\\\\" }, { "foo/bar/test", "foo/bar/test" }, - { "foo\\bar\\test", "foo/bar/test" }, + { "foo\\bar\\test", "foo\\bar\\test" }, { "/foo/bar/test/", "foo/bar/test" }, - { "\\foo\\bar\\test\\", "foo/bar/test" }, + { "\\foo\\bar\\test\\", "\\foo\\bar\\test\\" }, { "///foo//bar//test///", "foo/bar/test" }, { "./foo/././bar/test/./.", "foo/bar/test" }, { "./foo/././", "foo" }, diff --git a/tests/filename_sane.c b/tests/filename_sane.c index 3c1fd4f..86270b3 100644 --- a/tests/filename_sane.c +++ b/tests/filename_sane.c @@ -11,6 +11,9 @@ static const char *must_work[] = { "foobar", "test.txt", +#if !defined(_WIN32) && !defined(__WINDOWS__) && !defined(TEST_WIN32) + "\\foo", "foo\\", "foo\\bar", +#endif NULL, }; @@ -18,16 +21,14 @@ static const char *must_not_work[] = { ".", "..", "/foo", - "\\foo", "foo/", - "foo\\", "foo/bar", - "foo\\bar", NULL, }; static const char *must_not_work_here[] = { #if defined(_WIN32) || defined(__WINDOWS__) || defined(TEST_WIN32) + "\\foo", "foo\\", "foo\\bar", "fo<o", "fo>o", "fo:o", "fo\"o", "fo|o", "fo?o", "fo*o", "fo\ro", "CON", "PRN", "AUX", "NUL", |