From ab4aea7b40f8977fe3d67875d0acb4032cf9d0c5 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 8 Nov 2019 14:55:23 +0100 Subject: Extend is_filename_sane reserved character/name check - Instead of an open coded version, check against a list of bad names. On windows, the comparison needs to be done case insensitive. - If compiling for Windows, include the magic DOS device names in that list. - Also classify filenames as 'insane' if they contain back slashes, on all platforms. - If compiling for Windows, check for reserved characters. Signed-off-by: David Oberhollenzer --- lib/common/filename_sane.c | 47 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'lib/common') diff --git a/lib/common/filename_sane.c b/lib/common/filename_sane.c index 6b497c3..d089ba4 100644 --- a/lib/common/filename_sane.c +++ b/lib/common/filename_sane.c @@ -6,19 +6,58 @@ */ #include "common.h" +#include + +#ifdef _MSC_VER +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +static const char *bad_names[] = { + ".", + "..", +#ifdef _WIN32 + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", +#endif +}; + bool is_filename_sane(const char *name) { - if (name[0] == '.') { - if (name[1] == '\0') + size_t i = 0; + + for (i = 0; i < sizeof(bad_names) / sizeof(bad_names[0]); ++i) { +#ifdef _WIN32 + size_t len = strlen(bad_names[i]); + + if (strncasecmp(name, bad_names[i], len) != 0) + continue; + + if (name[len] == '\0') return false; - if (name[1] == '.' && name[2] == '\0') + if (name[len] == '.' && strchr(name + len + 1, '.') == NULL) return false; +#else + if (strcmp(name, bad_names[i]) == 0) + return false; +#endif } while (*name != '\0') { - if (*name == '/') + if (*name == '/' || *name == '\\') + return false; + +#ifdef _WIN32 + if (*name == '<' || *name == '>' || *name == ':') return false; + if (*name == '"' || *name == '|' || *name == '?') + return false; + if (*name == '*' || *name <= 31) + return false; +#endif + ++name; } -- cgit v1.2.3