aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--misc.c7
-rw-r--r--win32.c63
-rw-r--r--win32.h3
3 files changed, 72 insertions, 1 deletions
diff --git a/misc.c b/misc.c
index 985879c..8f80ee1 100644
--- a/misc.c
+++ b/misc.c
@@ -35,6 +35,7 @@
#include "manage.h"
#include "crypto.h"
#include "route.h"
+#include "win32.h"
#include "memdbg.h"
@@ -1114,7 +1115,11 @@ gen_path (const char *directory, const char *filename, struct gc_arena *gc)
if (safe_filename
&& strcmp (safe_filename, ".")
- && strcmp (safe_filename, ".."))
+ && strcmp (safe_filename, "..")
+#ifdef WIN32
+ && win_safe_filename (safe_filename)
+#endif
+ )
{
struct buffer out = alloc_buf_gc (256, gc);
char dirsep[2];
diff --git a/win32.c b/win32.c
index 6945ba1..516bf8e 100644
--- a/win32.c
+++ b/win32.c
@@ -753,4 +753,67 @@ getpass (const char *prompt)
return NULL;
}
+/*
+ * Return true if filename is safe to be used on Windows,
+ * by avoiding the following reserved names:
+ *
+ * CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9,
+ * LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, and CLOCK$
+ *
+ * See: http://msdn.microsoft.com/en-us/library/aa365247.aspx
+ * and http://msdn.microsoft.com/en-us/library/86k9f82k(VS.80).aspx
+ */
+
+static bool
+cmp_prefix (const char *str, const bool n, const char *pre)
+{
+ const size_t len = strlen (pre);
+ size_t i = 0;
+
+ if (!str)
+ return false;
+
+ while (true)
+ {
+ const int c1 = pre[i];
+ int c2 = str[i];
+ ++i;
+ if (c1 == '\0')
+ {
+ if (n)
+ {
+ if (isdigit (c2))
+ c2 = str[i];
+ else
+ return false;
+ }
+ return c2 == '\0' || c2 == '.';
+ }
+ else if (c2 == '\0')
+ return false;
+ if (c1 != tolower(c2))
+ return false;
+ }
+}
+
+bool
+win_safe_filename (const char *fn)
+{
+ if (cmp_prefix (fn, false, "con"))
+ return false;
+ if (cmp_prefix (fn, false, "prn"))
+ return false;
+ if (cmp_prefix (fn, false, "aux"))
+ return false;
+ if (cmp_prefix (fn, false, "nul"))
+ return false;
+ if (cmp_prefix (fn, true, "com"))
+ return false;
+ if (cmp_prefix (fn, true, "lpt"))
+ return false;
+ if (cmp_prefix (fn, false, "clock$"))
+ return false;
+ return true;
+}
+
#endif
diff --git a/win32.h b/win32.h
index 2697ae2..8cf8af2 100644
--- a/win32.h
+++ b/win32.h
@@ -247,5 +247,8 @@ char *getpass (const char *prompt);
/* Set Win32 security attributes structure to allow all access */
bool init_security_attributes_allow_all (struct security_attributes *obj);
+/* return true if filename is safe to be used on Windows */
+bool win_safe_filename (const char *fn);
+
#endif
#endif