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:
Johannes Schindelin
2019-12-04 23:09:11 +01:00
46 changed files with 984 additions and 88 deletions

View File

@ -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