[Python-checkins] bpo-36236: Fix _PyPathConfig_ComputeSysPath0() for empty argv (GH-12441)

Victor Stinner webhook-mailer at python.org
Tue Mar 19 13:22:59 EDT 2019


https://github.com/python/cpython/commit/fc96e5474a7bda1c5dec66420e4467fc9f7ca968
commit: fc96e5474a7bda1c5dec66420e4467fc9f7ca968
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-03-19T18:22:55+01:00
summary:

bpo-36236: Fix _PyPathConfig_ComputeSysPath0() for empty argv (GH-12441)

* _PyPathConfig_ComputeSysPath0() now returns 0 if argv is empty.
* Cleanup also _PyPathConfig_ComputeSysPath0() code: move variables
  definitions closer to where they are used.

files:
M Python/pathconfig.c

diff --git a/Python/pathconfig.c b/Python/pathconfig.c
index 743e1cd1ac0b..0ccb898e4290 100644
--- a/Python/pathconfig.c
+++ b/Python/pathconfig.c
@@ -573,79 +573,84 @@ Py_GetProgramName(void)
    Return 1 if the path is correctly resolved, but *path0_p can be NULL
    if the Unicode object fail to be created.
 
-   Return 0 if it fails to resolve the full path (and *path0_p will be NULL),
-   for example if the current working directory has been removed (bpo-36236).
+   Return 0 if it fails to resolve the full path (and *path0_p will be NULL).
+   For example, return 0 if the current working directory has been removed
+   (bpo-36236) or if argv is empty.
    */
 int
 _PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
 {
     assert(_PyWstrList_CheckConsistency(argv));
+    assert(*path0_p == NULL);
 
-    wchar_t *argv0;
-    wchar_t *p = NULL;
+    if (argv->length == 0) {
+        /* Leave sys.path unchanged if sys.argv is empty */
+        return 0;
+    }
+
+    wchar_t *argv0 = argv->items[0];
+    int have_module_arg = (wcscmp(argv0, L"-m") == 0);
+    int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
+
+    wchar_t *path0 = argv0;
     Py_ssize_t n = 0;
-    int have_script_arg = 0;
-    int have_module_arg = 0;
-#ifdef HAVE_READLINK
-    wchar_t link[MAXPATHLEN + 1];
-    wchar_t argv0copy[2 * MAXPATHLEN + 1];
-    int nr = 0;
-#endif
-#if defined(HAVE_REALPATH)
+
+#ifdef HAVE_REALPATH
     wchar_t fullpath[MAXPATHLEN];
 #elif defined(MS_WINDOWS)
     wchar_t fullpath[MAX_PATH];
 #endif
 
-    assert(*path0_p == NULL);
-
-    if (argv->length > 0) {
-        argv0 = argv->items[0];
-        have_module_arg = (wcscmp(argv0, L"-m") == 0);
-        have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
-    }
-
     if (have_module_arg) {
 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
-            if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
-                *path0_p = NULL;
-                return 0;
-            }
-            argv0 = fullpath;
-            n = wcslen(argv0);
+        if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
+            return 0;
+        }
+        path0 = fullpath;
 #else
-            argv0 = L".";
-            n = 1;
+        path0 = L".";
 #endif
+        n = wcslen(path0);
     }
 
 #ifdef HAVE_READLINK
-    if (have_script_arg)
-        nr = _Py_wreadlink(argv0, link, Py_ARRAY_LENGTH(link));
+    wchar_t link[MAXPATHLEN + 1];
+    int nr = 0;
+
+    if (have_script_arg) {
+        nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
+    }
     if (nr > 0) {
         /* It's a symlink */
         link[nr] = '\0';
-        if (link[0] == SEP)
-            argv0 = link; /* Link to absolute path */
-        else if (wcschr(link, SEP) == NULL)
-            ; /* Link without path */
+        if (link[0] == SEP) {
+            path0 = link; /* Link to absolute path */
+        }
+        else if (wcschr(link, SEP) == NULL) {
+            /* Link without path */
+        }
         else {
-            /* Must join(dirname(argv0), link) */
-            wchar_t *q = wcsrchr(argv0, SEP);
-            if (q == NULL)
-                argv0 = link; /* argv0 without path */
+            /* Must join(dirname(path0), link) */
+            wchar_t *q = wcsrchr(path0, SEP);
+            if (q == NULL) {
+                /* path0 without path */
+                path0 = link;
+            }
             else {
-                /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
-                wcsncpy(argv0copy, argv0, MAXPATHLEN);
-                q = wcsrchr(argv0copy, SEP);
+                /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
+                wchar_t path0copy[2 * MAXPATHLEN + 1];
+                wcsncpy(path0copy, path0, MAXPATHLEN);
+                q = wcsrchr(path0copy, SEP);
                 wcsncpy(q+1, link, MAXPATHLEN);
                 q[MAXPATHLEN + 1] = L'\0';
-                argv0 = argv0copy;
+                path0 = path0copy;
             }
         }
     }
 #endif /* HAVE_READLINK */
 
+    wchar_t *p = NULL;
+
 #if SEP == '\\'
     /* Special case for Microsoft filename syntax */
     if (have_script_arg) {
@@ -653,43 +658,46 @@ _PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
 #if defined(MS_WINDOWS)
         /* Replace the first element in argv with the full path. */
         wchar_t *ptemp;
-        if (GetFullPathNameW(argv0,
+        if (GetFullPathNameW(path0,
                            Py_ARRAY_LENGTH(fullpath),
                            fullpath,
                            &ptemp)) {
-            argv0 = fullpath;
+            path0 = fullpath;
         }
 #endif
-        p = wcsrchr(argv0, SEP);
+        p = wcsrchr(path0, SEP);
         /* Test for alternate separator */
-        q = wcsrchr(p ? p : argv0, '/');
+        q = wcsrchr(p ? p : path0, '/');
         if (q != NULL)
             p = q;
         if (p != NULL) {
-            n = p + 1 - argv0;
+            n = p + 1 - path0;
             if (n > 1 && p[-1] != ':')
                 n--; /* Drop trailing separator */
         }
     }
-#else /* All other filename syntaxes */
+#else
+    /* All other filename syntaxes */
     if (have_script_arg) {
 #if defined(HAVE_REALPATH)
-        if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
-            argv0 = fullpath;
+        if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
+            path0 = fullpath;
         }
 #endif
-        p = wcsrchr(argv0, SEP);
+        p = wcsrchr(path0, SEP);
     }
     if (p != NULL) {
-        n = p + 1 - argv0;
+        n = p + 1 - path0;
 #if SEP == '/' /* Special case for Unix filename syntax */
-        if (n > 1)
-            n--; /* Drop trailing separator */
+        if (n > 1) {
+            /* Drop trailing separator */
+            n--;
+        }
 #endif /* Unix */
     }
 #endif /* All others */
 
-    *path0_p = PyUnicode_FromWideChar(argv0, n);
+    *path0_p = PyUnicode_FromWideChar(path0, n);
     return 1;
 }
 



More information about the Python-checkins mailing list