summaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
authorLibravatar Johannes Schindelin <johannes.schindelin@gmx.de>2019-09-16 13:26:40 +0200
committerLibravatar Johannes Schindelin <johannes.schindelin@gmx.de>2019-12-05 15:37:09 +0100
commit2ddcccf97a717f9df17a4843c39e3c4f1df49fec (patch)
tree6d63983b124cf3793eee811811281ca131cebbb7 /compat
parentMerge branch 'win32-filenames-cannot-have-trailing-spaces-or-periods' (diff)
parentmingw: handle `subst`-ed "DOS drives" (diff)
downloadtgif-2ddcccf97a717f9df17a4843c39e3c4f1df49fec.tar.xz
Merge branch 'win32-accommodate-funny-drive-names'
While the only permitted drive letters for physical drives on Windows are letters of the US-English alphabet, this restriction does not apply to virtual drives assigned via `subst <letter>: <path>`. To prevent targeted attacks against systems where "funny" drive letters such as `1` or `!` are assigned, let's handle them as regular drive letters on Windows. This fixes CVE-2019-1351. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Diffstat (limited to 'compat')
-rw-r--r--compat/mingw.c34
-rw-r--r--compat/mingw.h11
2 files changed, 41 insertions, 4 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 11fb2de241..22adb7a8cb 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1989,6 +1989,30 @@ pid_t waitpid(pid_t pid, int *status, int options)
return -1;
}
+int mingw_has_dos_drive_prefix(const char *path)
+{
+ int i;
+
+ /*
+ * Does it start with an ASCII letter (i.e. highest bit not set),
+ * followed by a colon?
+ */
+ if (!(0x80 & (unsigned char)*path))
+ return *path && path[1] == ':' ? 2 : 0;
+
+ /*
+ * While drive letters must be letters of the English alphabet, it is
+ * possible to assign virtually _any_ Unicode character via `subst` as
+ * a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff
+ * like this:
+ *
+ * subst ֍: %USERPROFILE%\Desktop
+ */
+ for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++)
+ ; /* skip first UTF-8 character */
+ return path[i] == ':' ? i + 1 : 0;
+}
+
int mingw_skip_dos_drive_prefix(char **path)
{
int ret = has_dos_drive_prefix(*path);
@@ -2137,6 +2161,8 @@ int is_valid_win32_path(const char *path)
if (!protect_ntfs)
return 1;
+ skip_dos_drive_prefix((char **)&path);
+
for (;;) {
char c = *(path++);
switch (c) {
@@ -2158,6 +2184,14 @@ int is_valid_win32_path(const char *path)
preceding_space_or_period = 1;
i++;
continue;
+ case ':': /* DOS drive prefix was already skipped */
+ case '<': case '>': case '"': case '|': case '?': case '*':
+ /* illegal character */
+ return 0;
+ default:
+ if (c > '\0' && c < '\x20')
+ /* illegal character */
+ return 0;
}
preceding_space_or_period = 0;
i++;
diff --git a/compat/mingw.h b/compat/mingw.h
index 8c49c1d09b..17064665d9 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -394,8 +394,8 @@ HANDLE winansi_get_osfhandle(int fd);
* git specific compatibility
*/
-#define has_dos_drive_prefix(path) \
- (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
+int mingw_has_dos_drive_prefix(const char *path);
+#define has_dos_drive_prefix mingw_has_dos_drive_prefix
int mingw_skip_dos_drive_prefix(char **path);
#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
static inline int mingw_is_dir_sep(int c)
@@ -431,8 +431,11 @@ int mingw_offset_1st_component(const char *path);
/**
* Verifies that the given path is a valid one on Windows.
*
- * In particular, path segments are disallowed which end in a period or a
- * space (except the special directories `.` and `..`).
+ * In particular, path segments are disallowed which
+ *
+ * - end in a period or a space (except the special directories `.` and `..`).
+ *
+ * - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
*
* Returns 1 upon success, otherwise 0.
*/