bpo-28441: Ensure `.exe` suffix in `sys.executable` on MinGW and Cygwin (GH-4348)

This is needed to even the run the test suite on buildbots for affected platforms; e.g.:

```
./python.exe  ./Tools/scripts/run_tests.py -j 1 -u all -W --slowest --fail-env-changed --timeout=11700 -j2
/home/embray/src/python/test-worker/3.x.test-worker/build/python -u -W default -bb -E -W error::BytesWarning -m test -r -w -j 1 -u all -W --slowest --fail-env-changed --timeout=11700 -j2
Traceback (most recent call last):
  File "./Tools/scripts/run_tests.py", line 56, in <module>
    main(sys.argv[1:])
  File "./Tools/scripts/run_tests.py", line 52, in main
    os.execv(sys.executable, args)
PermissionError: [Errno 13] Permission denied
make: *** [Makefile:1073: buildbottest] Error 1
```
This commit is contained in:
E. M. Bray 2018-10-05 13:38:50 +02:00 committed by INADA Naoki
parent fc7d1b3b6a
commit 7a7693e9cb
2 changed files with 48 additions and 0 deletions

View File

@ -0,0 +1,3 @@
On Cygwin and MinGW, ensure that ``sys.executable`` always includes the full
filename in the path, including the ``.exe`` suffix (unless it is a symbolic
link).

View File

@ -296,6 +296,41 @@ absolutize(wchar_t *path)
}
#if defined(__CYGWIN__) || defined(__MINGW32__)
/* add_exe_suffix requires that progpath be allocated at least
MAXPATHLEN + 1 bytes.
*/
#ifndef EXE_SUFFIX
#define EXE_SUFFIX L".exe"
#endif
static void
add_exe_suffix(wchar_t *progpath)
{
/* Check for already have an executable suffix */
size_t n = wcslen(progpath);
size_t s = wcslen(EXE_SUFFIX);
if (wcsncasecmp(EXE_SUFFIX, progpath+n-s, s) != 0) {
if (n + s > MAXPATHLEN) {
Py_FatalError("progpath overflow in getpath.c's add_exe_suffix()");
}
/* Save original path for revert */
wchar_t orig[MAXPATHLEN+1];
wcsncpy(orig, progpath, MAXPATHLEN);
wcsncpy(progpath+n, EXE_SUFFIX, s);
progpath[n+s] = '\0';
if (!isxfile(progpath)) {
/* Path that added suffix is invalid */
wcsncpy(progpath, orig, MAXPATHLEN);
}
}
}
#endif
/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
bytes long.
*/
@ -605,6 +640,16 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
absolutize(program_full_path);
}
#if defined(__CYGWIN__) || defined(__MINGW32__)
/* For these platforms it is necessary to ensure that the .exe suffix
* is appended to the filename, otherwise there is potential for
* sys.executable to return the name of a directory under the same
* path (bpo-28441).
*/
if (program_full_path[0] != '\0') {
add_exe_suffix(program_full_path);
}
#endif
config->program_full_path = _PyMem_RawWcsdup(program_full_path);
if (config->program_full_path == NULL) {