From 03e6e3f69accd1b69a32e508ac53ca2737296d2f Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Thu, 9 Nov 2017 15:33:17 +0100 Subject: [PATCH 1/3] bpo-28441 Ensures that EXE_SUFFIX is appended to the end of sys.executable on Cygwin and MinGW. (GH-4348) --- Makefile.pre.in | 1 + .../2018-10-04-15-53-14.bpo-28441.2sQENe.rst | 3 ++ Modules/getpath.c | 51 ++++++++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-10-04-15-53-14.bpo-28441.2sQENe.rst diff --git a/Makefile.pre.in b/Makefile.pre.in index 333ab9b38240f20..c06d8f9f8867b6d 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -757,6 +757,7 @@ Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile -DEXEC_PREFIX='"$(exec_prefix)"' \ -DVERSION='"$(VERSION)"' \ -DVPATH='"$(VPATH)"' \ + -DEXE_SUFFIX='"$(EXE)"' \ -o $@ $(srcdir)/Modules/getpath.c Programs/python.o: $(srcdir)/Programs/python.c diff --git a/Misc/NEWS.d/next/Library/2018-10-04-15-53-14.bpo-28441.2sQENe.rst b/Misc/NEWS.d/next/Library/2018-10-04-15-53-14.bpo-28441.2sQENe.rst new file mode 100644 index 000000000000000..45143c2a54ac409 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-10-04-15-53-14.bpo-28441.2sQENe.rst @@ -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). diff --git a/Modules/getpath.c b/Modules/getpath.c index 041cb14b4b9c165..bc3834970d60cc3 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -102,8 +102,9 @@ extern "C" { #endif -#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH) -#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined" +#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || \ + !defined(VPATH) || !defined(EXE_SUFFIX) +#error "PREFIX, EXEC_PREFIX, VERSION, VPATH, and EXE_SUFFIX must be constant defined" #endif #ifndef LANDMARK @@ -296,6 +297,43 @@ absolutize(wchar_t *path) } +#if defined(__CYGWIN__) || defined(__MINGW32__) +/* add_exe_suffix requires that progpath be allocated at least + MAXPATHLEN + 1 bytes. +*/ +static void +add_exe_suffix(wchar_t *progpath) +{ + wchar_t *_suffix = Py_DecodeLocale(EXE_SUFFIX, NULL); + if (_suffix == NULL) { + Py_FatalError("Unable to decode suffix variables in getpath.c: " + "memory error"); + } + + /* Check for already have an executable suffix */ + size_t n = wcslen(progpath); + size_t s = wcslen(_suffix); + if (wcsncasecmp(_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, _suffix, s); + progpath[n+s] = '\0'; + + if (!isxfile(progpath)) { + /* Path that added suffix is invalid */ + wcsncpy(progpath, orig, MAXPATHLEN); + } + } + PyMem_RawFree(_suffix); +} +#endif + + /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ @@ -605,6 +643,15 @@ 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 (EXE_SUFFIX[0] != '\0' && 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) { From 8c7e0a008ae6f8be4fd5efbd33bc4b27132cd689 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 Oct 2018 12:24:16 +0200 Subject: [PATCH 2/3] simplify by hard-coding EXE_SUFFIX on the affected platforms it will always be .exe --- Makefile.pre.in | 1 - Modules/getpath.c | 25 +++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index c06d8f9f8867b6d..333ab9b38240f20 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -757,7 +757,6 @@ Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile -DEXEC_PREFIX='"$(exec_prefix)"' \ -DVERSION='"$(VERSION)"' \ -DVPATH='"$(VPATH)"' \ - -DEXE_SUFFIX='"$(EXE)"' \ -o $@ $(srcdir)/Modules/getpath.c Programs/python.o: $(srcdir)/Programs/python.c diff --git a/Modules/getpath.c b/Modules/getpath.c index bc3834970d60cc3..d4208bcda3486da 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -102,9 +102,8 @@ extern "C" { #endif -#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || \ - !defined(VPATH) || !defined(EXE_SUFFIX) -#error "PREFIX, EXEC_PREFIX, VERSION, VPATH, and EXE_SUFFIX must be constant defined" +#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH) +#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined" #endif #ifndef LANDMARK @@ -301,19 +300,18 @@ absolutize(wchar_t *path) /* 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) { - wchar_t *_suffix = Py_DecodeLocale(EXE_SUFFIX, NULL); - if (_suffix == NULL) { - Py_FatalError("Unable to decode suffix variables in getpath.c: " - "memory error"); - } - /* Check for already have an executable suffix */ size_t n = wcslen(progpath); - size_t s = wcslen(_suffix); - if (wcsncasecmp(_suffix, progpath+n-s, s) != 0) { + 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()"); } @@ -321,7 +319,7 @@ add_exe_suffix(wchar_t *progpath) wchar_t orig[MAXPATHLEN+1]; wcsncpy(orig, progpath, MAXPATHLEN); - wcsncpy(progpath+n, _suffix, s); + wcsncpy(progpath+n, EXE_SUFFIX, s); progpath[n+s] = '\0'; if (!isxfile(progpath)) { @@ -329,7 +327,6 @@ add_exe_suffix(wchar_t *progpath) wcsncpy(progpath, orig, MAXPATHLEN); } } - PyMem_RawFree(_suffix); } #endif @@ -649,7 +646,7 @@ calculate_program_full_path(const _PyCoreConfig *core_config, * sys.executable to return the name of a directory under the same * path (bpo-28441). */ - if (EXE_SUFFIX[0] != '\0' && program_full_path[0] != '\0') + if (program_full_path[0] != '\0') add_exe_suffix(program_full_path); #endif From adc7b92b1896f58da38d628118aacc18732d1b15 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 Oct 2018 12:59:38 +0200 Subject: [PATCH 3/3] use {} for new code --- Modules/getpath.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index d4208bcda3486da..521bc6e35ed3ee9 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -646,8 +646,9 @@ calculate_program_full_path(const _PyCoreConfig *core_config, * sys.executable to return the name of a directory under the same * path (bpo-28441). */ - if (program_full_path[0] != '\0') + if (program_full_path[0] != '\0') { add_exe_suffix(program_full_path); + } #endif config->program_full_path = _PyMem_RawWcsdup(program_full_path);