Sync with 2.20.2
* maint-2.20: (36 commits) 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 quote-stress-test: offer to test quoting arguments for MSYS2 sh t6130/t9350: prepare for stringent Win32 path validation quote-stress-test: allow skipping some trials quote-stress-test: accept arguments to test via the command-line tests: add a helper to stress test argument quoting mingw: fix quoting of arguments Disallow dubiously-nested submodule git directories ...
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
@ -2464,6 +2488,50 @@ static void setup_windows_environment(void)
|
||||
setenv("TERM", "cygwin", 1);
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable MSVCRT command line wildcard expansion (__getmainargs called from
|
||||
* mingw startup code, see init.c in mingw runtime).
|
||||
|
Reference in New Issue
Block a user