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

INADA Naoki webhook-mailer at python.org
Fri Oct 5 07:38:55 EDT 2018


https://github.com/python/cpython/commit/7a7693e9cb12e5571c76331db56a28eef9acb6e0
commit: 7a7693e9cb12e5571c76331db56a28eef9acb6e0
branch: master
author: E. M. Bray <erik.m.bray at gmail.com>
committer: INADA Naoki <methane at users.noreply.github.com>
date: 2018-10-05T20:38:50+09:00
summary:

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

files:
A Misc/NEWS.d/next/Library/2018-10-04-15-53-14.bpo-28441.2sQENe.rst
M Modules/getpath.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 000000000000..45143c2a54ac
--- /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 041cb14b4b9c..521bc6e35ed3 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -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) {



More information about the Python-checkins mailing list