Skip to content

Commit fc96e54

Browse files
authored
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.
1 parent cb90c89 commit fc96e54

File tree

1 file changed

+63
-55
lines changed

1 file changed

+63
-55
lines changed

Python/pathconfig.c

Lines changed: 63 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -573,123 +573,131 @@ Py_GetProgramName(void)
573573
Return 1 if the path is correctly resolved, but *path0_p can be NULL
574574
if the Unicode object fail to be created.
575575
576-
Return 0 if it fails to resolve the full path (and *path0_p will be NULL),
577-
for example if the current working directory has been removed (bpo-36236).
576+
Return 0 if it fails to resolve the full path (and *path0_p will be NULL).
577+
For example, return 0 if the current working directory has been removed
578+
(bpo-36236) or if argv is empty.
578579
*/
579580
int
580581
_PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
581582
{
582583
assert(_PyWstrList_CheckConsistency(argv));
584+
assert(*path0_p == NULL);
583585

584-
wchar_t *argv0;
585-
wchar_t *p = NULL;
586+
if (argv->length == 0) {
587+
/* Leave sys.path unchanged if sys.argv is empty */
588+
return 0;
589+
}
590+
591+
wchar_t *argv0 = argv->items[0];
592+
int have_module_arg = (wcscmp(argv0, L"-m") == 0);
593+
int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
594+
595+
wchar_t *path0 = argv0;
586596
Py_ssize_t n = 0;
587-
int have_script_arg = 0;
588-
int have_module_arg = 0;
589-
#ifdef HAVE_READLINK
590-
wchar_t link[MAXPATHLEN + 1];
591-
wchar_t argv0copy[2 * MAXPATHLEN + 1];
592-
int nr = 0;
593-
#endif
594-
#if defined(HAVE_REALPATH)
597+
598+
#ifdef HAVE_REALPATH
595599
wchar_t fullpath[MAXPATHLEN];
596600
#elif defined(MS_WINDOWS)
597601
wchar_t fullpath[MAX_PATH];
598602
#endif
599603

600-
assert(*path0_p == NULL);
601-
602-
if (argv->length > 0) {
603-
argv0 = argv->items[0];
604-
have_module_arg = (wcscmp(argv0, L"-m") == 0);
605-
have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
606-
}
607-
608604
if (have_module_arg) {
609605
#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
610-
if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
611-
*path0_p = NULL;
612-
return 0;
613-
}
614-
argv0 = fullpath;
615-
n = wcslen(argv0);
606+
if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
607+
return 0;
608+
}
609+
path0 = fullpath;
616610
#else
617-
argv0 = L".";
618-
n = 1;
611+
path0 = L".";
619612
#endif
613+
n = wcslen(path0);
620614
}
621615

622616
#ifdef HAVE_READLINK
623-
if (have_script_arg)
624-
nr = _Py_wreadlink(argv0, link, Py_ARRAY_LENGTH(link));
617+
wchar_t link[MAXPATHLEN + 1];
618+
int nr = 0;
619+
620+
if (have_script_arg) {
621+
nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
622+
}
625623
if (nr > 0) {
626624
/* It's a symlink */
627625
link[nr] = '\0';
628-
if (link[0] == SEP)
629-
argv0 = link; /* Link to absolute path */
630-
else if (wcschr(link, SEP) == NULL)
631-
; /* Link without path */
626+
if (link[0] == SEP) {
627+
path0 = link; /* Link to absolute path */
628+
}
629+
else if (wcschr(link, SEP) == NULL) {
630+
/* Link without path */
631+
}
632632
else {
633-
/* Must join(dirname(argv0), link) */
634-
wchar_t *q = wcsrchr(argv0, SEP);
635-
if (q == NULL)
636-
argv0 = link; /* argv0 without path */
633+
/* Must join(dirname(path0), link) */
634+
wchar_t *q = wcsrchr(path0, SEP);
635+
if (q == NULL) {
636+
/* path0 without path */
637+
path0 = link;
638+
}
637639
else {
638-
/* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
639-
wcsncpy(argv0copy, argv0, MAXPATHLEN);
640-
q = wcsrchr(argv0copy, SEP);
640+
/* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
641+
wchar_t path0copy[2 * MAXPATHLEN + 1];
642+
wcsncpy(path0copy, path0, MAXPATHLEN);
643+
q = wcsrchr(path0copy, SEP);
641644
wcsncpy(q+1, link, MAXPATHLEN);
642645
q[MAXPATHLEN + 1] = L'\0';
643-
argv0 = argv0copy;
646+
path0 = path0copy;
644647
}
645648
}
646649
}
647650
#endif /* HAVE_READLINK */
648651

652+
wchar_t *p = NULL;
653+
649654
#if SEP == '\\'
650655
/* Special case for Microsoft filename syntax */
651656
if (have_script_arg) {
652657
wchar_t *q;
653658
#if defined(MS_WINDOWS)
654659
/* Replace the first element in argv with the full path. */
655660
wchar_t *ptemp;
656-
if (GetFullPathNameW(argv0,
661+
if (GetFullPathNameW(path0,
657662
Py_ARRAY_LENGTH(fullpath),
658663
fullpath,
659664
&ptemp)) {
660-
argv0 = fullpath;
665+
path0 = fullpath;
661666
}
662667
#endif
663-
p = wcsrchr(argv0, SEP);
668+
p = wcsrchr(path0, SEP);
664669
/* Test for alternate separator */
665-
q = wcsrchr(p ? p : argv0, '/');
670+
q = wcsrchr(p ? p : path0, '/');
666671
if (q != NULL)
667672
p = q;
668673
if (p != NULL) {
669-
n = p + 1 - argv0;
674+
n = p + 1 - path0;
670675
if (n > 1 && p[-1] != ':')
671676
n--; /* Drop trailing separator */
672677
}
673678
}
674-
#else /* All other filename syntaxes */
679+
#else
680+
/* All other filename syntaxes */
675681
if (have_script_arg) {
676682
#if defined(HAVE_REALPATH)
677-
if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
678-
argv0 = fullpath;
683+
if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
684+
path0 = fullpath;
679685
}
680686
#endif
681-
p = wcsrchr(argv0, SEP);
687+
p = wcsrchr(path0, SEP);
682688
}
683689
if (p != NULL) {
684-
n = p + 1 - argv0;
690+
n = p + 1 - path0;
685691
#if SEP == '/' /* Special case for Unix filename syntax */
686-
if (n > 1)
687-
n--; /* Drop trailing separator */
692+
if (n > 1) {
693+
/* Drop trailing separator */
694+
n--;
695+
}
688696
#endif /* Unix */
689697
}
690698
#endif /* All others */
691699

692-
*path0_p = PyUnicode_FromWideChar(argv0, n);
700+
*path0_p = PyUnicode_FromWideChar(path0, n);
693701
return 1;
694702
}
695703

0 commit comments

Comments
 (0)