New submission from Christian Ullrich:

I'm trying to do something that may be slightly tricky, and I think I just 
found a vintage 1997 bug. Please correct me if I'm wrong.

This is PC/getpathp.c from current master:

430: static void
431: get_progpath(void)
432: {
433:     extern wchar_t *Py_GetProgramName(void);
434:     wchar_t *path = _wgetenv(L"PATH");
435:     wchar_t *prog = Py_GetProgramName();
436: 
437: #ifdef Py_ENABLE_SHARED
438:     extern HANDLE PyWin_DLLhModule;
439:     /* static init of progpath ensures final char remains \0 */
440:     if (PyWin_DLLhModule)
441:         if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN))
442:             dllpath[0] = 0;
443: #else
444:     dllpath[0] = 0;
445: #endif
446:     if (GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
447:         return;
448:     if (prog == NULL || *prog == '\0')
449:         prog = L"python";

Lines 446-447 have been like this ever since Guido wrote them twenty years ago. 
I think the logic is the wrong way around. As it is now, the function always 
returns on line 447 because GetModuleFileNameW() *always* succeeds (returns 
nonzero). Hence, everything below line 447 is dead code.

GetModuleFileNameW(NULL, ...) fills the buffer with the path to the executable 
the current process was created from. It returns the number of characters put 
into the buffer, or zero on error. However, the only way *this* call could fail 
is if the code was being executed outside of any process, something that 
clearly cannot happen.

Prior to August 1997, the relevant bit of code looked like this:

156:    if (!GetModuleFileName(NULL, progpath, MAXPATHLEN))
157:        progpath[0] = '\0'; /* failure */


This bug, if it is one, would only manifest when initializing an embedded 
interpreter using a different argv[0] than that of the actual host process, 
because if the host process is a python.exe, it very likely runs inside a 
standard installation or venv anyway. What I am trying is to make an 
interpreter running in a third-party host process take site-packages from a 
venv.

Doing this (argv[0] different from actual host process) may not be entirely 
proper itself, but then again, why would Py_SetProgramName() even exist 
otherwise?

Suggested fix:

diff --git a/PC/getpathp.c b/PC/getpathp.c
index 8380e1bcfa..abb5e54c9f 100644
--- a/PC/getpathp.c
+++ b/PC/getpathp.c
@@ -443,8 +443,7 @@ get_progpath(void)
 #else
     dllpath[0] = 0;
 #endif
-    if (!GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
-        return;
+    GetModuleFileNameW(NULL, progpath, MAXPATHLEN);
     if (prog == NULL || *prog == '\0')
         prog = L"python";

Since the call to GetModuleFileNameW() cannot possibly fail, there is no real 
point in checking its return value.

----------
components: Windows
messages: 301306
nosy: Christian.Ullrich, paul.moore, steve.dower, tim.golden, zach.ware
priority: normal
severity: normal
status: open
title: Embedded initialization ignores Py_SetProgramName()
type: behavior
versions: Python 3.6, Python 3.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue31349>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to