summaryrefslogtreecommitdiff
path: root/compat/mingw.c
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2019-12-04 22:06:31 (GMT)
committerJohannes Schindelin <johannes.schindelin@gmx.de>2019-12-06 15:31:30 (GMT)
commit7fd9fd94fb8f23b86578ed86906b8caf0417db82 (patch)
tree816a507d8bc5b84c18243b642896e18180ead938 /compat/mingw.c
parent5fa0f5238b0cd46cfe7f6fa76c3f526ea98148d9 (diff)
parentd9589d4051537c387b70dc76e430c61b4c85a86d (diff)
downloadgit-7fd9fd94fb8f23b86578ed86906b8caf0417db82.zip
git-7fd9fd94fb8f23b86578ed86906b8caf0417db82.tar.gz
git-7fd9fd94fb8f23b86578ed86906b8caf0417db82.tar.bz2
Sync with 2.22.2
* maint-2.22: (43 commits) Git 2.22.2 Git 2.21.1 mingw: sh arguments need quoting in more circumstances mingw: fix quoting of empty arguments for `sh` mingw: use MSYS2 quoting even when spawning shell scripts mingw: detect when MSYS2's sh is to be spawned more robustly t7415: drop v2.20.x-specific work-around Git 2.20.2 t7415: adjust test for dubiously-nested submodule gitdirs for v2.20.x Git 2.19.3 Git 2.18.2 Git 2.17.3 Git 2.16.6 test-drop-caches: use `has_dos_drive_prefix()` Git 2.15.4 Git 2.14.6 mingw: handle `subst`-ed "DOS drives" mingw: refuse to access paths with trailing spaces or periods mingw: refuse to access paths with illegal characters unpack-trees: let merged_entry() pass through do_add_entry()'s errors ...
Diffstat (limited to 'compat/mingw.c')
-rw-r--r--compat/mingw.c101
1 files changed, 92 insertions, 9 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 738f0a8..7cbde1d 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -390,6 +390,12 @@ int mingw_mkdir(const char *path, int mode)
{
int ret;
wchar_t wpath[MAX_PATH];
+
+ if (!is_valid_win32_path(path)) {
+ errno = EINVAL;
+ return -1;
+ }
+
if (xutftowcs_path(wpath, path) < 0)
return -1;
ret = _wmkdir(wpath);
@@ -463,7 +469,7 @@ int mingw_open (const char *filename, int oflags, ...)
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
va_list args;
unsigned mode;
- int fd;
+ int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
wchar_t wfilename[MAX_PATH];
open_fn_t open_fn;
@@ -471,6 +477,11 @@ int mingw_open (const char *filename, int oflags, ...)
mode = va_arg(args, int);
va_end(args);
+ if (!is_valid_win32_path(filename)) {
+ errno = create ? EINVAL : ENOENT;
+ return -1;
+ }
+
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
@@ -537,6 +548,11 @@ FILE *mingw_fopen (const char *filename, const char *otype)
int hide = needs_hiding(filename);
FILE *file;
wchar_t wfilename[MAX_PATH], wotype[4];
+ if (!is_valid_win32_path(filename)) {
+ int create = otype && strchr(otype, 'w');
+ errno = create ? EINVAL : ENOENT;
+ return NULL;
+ }
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
if (xutftowcs_path(wfilename, filename) < 0 ||
@@ -559,6 +575,11 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
int hide = needs_hiding(filename);
FILE *file;
wchar_t wfilename[MAX_PATH], wotype[4];
+ if (!is_valid_win32_path(filename)) {
+ int create = otype && strchr(otype, 'w');
+ errno = create ? EINVAL : ENOENT;
+ return NULL;
+ }
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
if (xutftowcs_path(wfilename, filename) < 0 ||
@@ -1052,7 +1073,7 @@ static const char *quote_arg_msvc(const char *arg)
p++;
len++;
}
- if (*p == '"')
+ if (*p == '"' || !*p)
n += count*2 + 1;
continue;
}
@@ -1074,16 +1095,19 @@ static const char *quote_arg_msvc(const char *arg)
count++;
*d++ = *arg++;
}
- if (*arg == '"') {
+ if (*arg == '"' || !*arg) {
while (count-- > 0)
*d++ = '\\';
+ /* don't escape the surrounding end quote */
+ if (!*arg)
+ break;
*d++ = '\\';
}
}
*d++ = *arg++;
}
*d++ = '"';
- *d++ = 0;
+ *d++ = '\0';
return q;
}
@@ -1096,13 +1120,14 @@ static const char *quote_arg_msys2(const char *arg)
for (p = arg; *p; p++) {
int ws = isspace(*p);
- if (!ws && *p != '\\' && *p != '"' && *p != '{')
+ if (!ws && *p != '\\' && *p != '"' && *p != '{' && *p != '\'' &&
+ *p != '?' && *p != '*' && *p != '~')
continue;
if (!buf.len)
strbuf_addch(&buf, '"');
if (p != p2)
strbuf_add(&buf, p2, p - p2);
- if (!ws && *p != '{')
+ if (*p == '\\' || *p == '"')
strbuf_addch(&buf, '\\');
p2 = p;
}
@@ -1112,7 +1137,7 @@ static const char *quote_arg_msys2(const char *arg)
else if (!buf.len)
return arg;
else
- strbuf_add(&buf, p2, p - p2),
+ strbuf_add(&buf, p2, p - p2);
strbuf_addch(&buf, '"');
return strbuf_detach(&buf, 0);
@@ -1367,7 +1392,10 @@ static inline int match_last_path_component(const char *path, size_t *len,
static int is_msys2_sh(const char *cmd)
{
- if (cmd && !strcmp(cmd, "sh")) {
+ if (!cmd)
+ return 0;
+
+ if (!strcmp(cmd, "sh")) {
static int ret = -1;
char *p;
@@ -1387,6 +1415,16 @@ static int is_msys2_sh(const char *cmd)
}
return ret;
}
+
+ if (ends_with(cmd, "\\sh.exe")) {
+ static char *sh;
+
+ if (!sh)
+ sh = path_lookup("sh", 0);
+
+ return !fspathcmp(cmd, sh);
+ }
+
return 0;
}
@@ -1402,7 +1440,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
BOOL ret;
HANDLE cons;
const char *(*quote_arg)(const char *arg) =
- is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc;
+ is_msys2_sh(cmd ? cmd : *argv) ?
+ quote_arg_msys2 : quote_arg_msvc;
do_unset_environment_variables();
@@ -2361,6 +2400,50 @@ static void setup_windows_environment(void)
}
}
+int is_valid_win32_path(const char *path)
+{
+ int preceding_space_or_period = 0, i = 0, periods = 0;
+
+ if (!protect_ntfs)
+ return 1;
+
+ skip_dos_drive_prefix((char **)&path);
+
+ for (;;) {
+ char c = *(path++);
+ switch (c) {
+ case '\0':
+ case '/': case '\\':
+ /* cannot end in ` ` or `.`, except for `.` and `..` */
+ if (preceding_space_or_period &&
+ (i != periods || periods > 2))
+ return 0;
+ if (!c)
+ return 1;
+
+ i = periods = preceding_space_or_period = 0;
+ continue;
+ case '.':
+ periods++;
+ /* fallthru */
+ case ' ':
+ 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++;
+ }
+}
+
#if !defined(_MSC_VER)
/*
* Disable MSVCRT command line wildcard expansion (__getmainargs called from