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.
This commit is contained in:
Victor Stinner 2019-03-19 18:22:55 +01:00 committed by GitHub
parent cb90c89de1
commit fc96e5474a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 63 additions and 55 deletions

View File

@ -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);
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;
}