blob: efc26273a29f4669064ac88ce1a73f3dec61e046 [file] [log] [blame]
From 9198107f367183b53c8bdc44c917bc334f09e21f Mon Sep 17 00:00:00 2001
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Date: Thu, 5 Sep 2019 13:44:21 +0200
Subject: mingw: refuse to access paths with illegal characters
Certain characters are not admissible in file names on Windows, even if
Cygwin/MSYS2 (and therefore, Git for Windows' Bash) pretend that they
are, e.g. `:`, `<`, `>`, etc
Let's disallow those characters explicitly in Windows builds of Git.
Note: just like trailing spaces or periods, it _is_ possible on Windows
to create commits adding files with such illegal characters, as long as
the operation leaves the worktree untouched. To allow for that, we
continue to guard `is_valid_win32_path()` behind the config setting
`core.protectNTFS`, so that users _can_ continue to do that, as long as
they turn the protections off via that config setting.
Among other problems, this prevents Git from trying to write to an "NTFS
Alternate Data Stream" (which refers to metadata stored alongside a
file, under a special name: "<filename>:<stream-name>"). This fix
therefore also prevents an attack vector that was exploited in
demonstrations of a number of recently-fixed security bugs.
Further reading on illegal characters in Win32 filenames:
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
(cherry picked from commit 817ddd64c20b29b2d86b3a0589f7ff88d1279109)
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
compat/mingw.c | 10 ++++++++++
compat/mingw.h | 7 +++++--
t/t0060-path-utils.sh | 4 +++-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw.c
index 386aa94acb..806822744f 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2447,6 +2447,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) {
@@ -2468,6 +2470,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 1d7e9d7c9d..38fee3482e 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -482,8 +482,11 @@ extern char *mingw_query_user_email(void);
/**
* 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.
*/
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index dc245c7dfe..2052583489 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -460,13 +460,15 @@ test_expect_success MINGW 'is_valid_path() on Windows' '
win32 \
"win32 x" \
../hello.txt \
+ C:\\git \
\
--not \
"win32 " \
"win32 /x " \
"win32." \
"win32 . ." \
- .../hello.txt
+ .../hello.txt \
+ colon:test
'
test_done
--
2.24.0.393.g34dc348eaf