Skip to content

Commit e5897b6

Browse files
miss-islingtonembray
authored andcommitted
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 ``` (cherry picked from commit 7a7693e) Co-authored-by: E. M. Bray <[email protected]>
1 parent 2632474 commit e5897b6

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
On Cygwin and MinGW, ensure that ``sys.executable`` always includes the full
2+
filename in the path, including the ``.exe`` suffix (unless it is a symbolic
3+
link).

Modules/getpath.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,41 @@ absolutize(wchar_t *path)
296296
}
297297

298298

299+
#if defined(__CYGWIN__) || defined(__MINGW32__)
300+
/* add_exe_suffix requires that progpath be allocated at least
301+
MAXPATHLEN + 1 bytes.
302+
*/
303+
304+
#ifndef EXE_SUFFIX
305+
#define EXE_SUFFIX L".exe"
306+
#endif
307+
308+
static void
309+
add_exe_suffix(wchar_t *progpath)
310+
{
311+
/* Check for already have an executable suffix */
312+
size_t n = wcslen(progpath);
313+
size_t s = wcslen(EXE_SUFFIX);
314+
if (wcsncasecmp(EXE_SUFFIX, progpath+n-s, s) != 0) {
315+
if (n + s > MAXPATHLEN) {
316+
Py_FatalError("progpath overflow in getpath.c's add_exe_suffix()");
317+
}
318+
/* Save original path for revert */
319+
wchar_t orig[MAXPATHLEN+1];
320+
wcsncpy(orig, progpath, MAXPATHLEN);
321+
322+
wcsncpy(progpath+n, EXE_SUFFIX, s);
323+
progpath[n+s] = '\0';
324+
325+
if (!isxfile(progpath)) {
326+
/* Path that added suffix is invalid */
327+
wcsncpy(progpath, orig, MAXPATHLEN);
328+
}
329+
}
330+
}
331+
#endif
332+
333+
299334
/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
300335
bytes long.
301336
*/
@@ -605,6 +640,16 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
605640
if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
606641
absolutize(program_full_path);
607642
}
643+
#if defined(__CYGWIN__) || defined(__MINGW32__)
644+
/* For these platforms it is necessary to ensure that the .exe suffix
645+
* is appended to the filename, otherwise there is potential for
646+
* sys.executable to return the name of a directory under the same
647+
* path (bpo-28441).
648+
*/
649+
if (program_full_path[0] != '\0') {
650+
add_exe_suffix(program_full_path);
651+
}
652+
#endif
608653

609654
config->program_full_path = _PyMem_RawWcsdup(program_full_path);
610655
if (config->program_full_path == NULL) {

0 commit comments

Comments
 (0)