Sync with 2.23.1
* maint-2.23: (44 commits) Git 2.23.1 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 ...
This commit is contained in:
101
compat/mingw.c
101
compat/mingw.c
@ -392,6 +392,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);
|
||||
@ -465,7 +471,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;
|
||||
|
||||
@ -473,6 +479,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";
|
||||
|
||||
@ -539,6 +550,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 ||
|
||||
@ -561,6 +577,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 ||
|
||||
@ -1054,7 +1075,7 @@ static const char *quote_arg_msvc(const char *arg)
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
if (*p == '"')
|
||||
if (*p == '"' || !*p)
|
||||
n += count*2 + 1;
|
||||
continue;
|
||||
}
|
||||
@ -1076,16 +1097,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;
|
||||
}
|
||||
|
||||
@ -1098,13 +1122,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;
|
||||
}
|
||||
@ -1114,7 +1139,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);
|
||||
@ -1371,7 +1396,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;
|
||||
|
||||
@ -1391,6 +1419,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;
|
||||
}
|
||||
|
||||
@ -1406,7 +1444,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();
|
||||
|
||||
@ -2367,6 +2406,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
|
||||
|
Reference in New Issue
Block a user