From 723f71abf7ab0a7be394f9f7b2daa9ecdf6fb1eb Mon Sep 17 00:00:00 2001 From: Benoit Hudson Date: Fri, 6 Dec 2019 14:15:03 -0500 Subject: [PATCH] bpo-37931: Fix crash on OSX re-initializing os.environ (GH-15428) On most platforms, the `environ` symbol is accessible everywhere. In a dylib on OSX, it's not easily accessible, you need to find it with _NSGetEnviron. The code was caching the *value* of environ. But a setenv() can change the value, leaving garbage at the old value. Fix: don't cache the value of environ, just read it every time. --- Misc/ACKS | 1 + .../macOS/2019-08-23-12-14-34.bpo-37931.goYgQj.rst | 3 +++ Modules/posixmodule.c | 10 +++++----- 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2019-08-23-12-14-34.bpo-37931.goYgQj.rst diff --git a/Misc/ACKS b/Misc/ACKS index 357ce024e9e..239d06ffd0b 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -733,6 +733,7 @@ Miro Hrončok Chiu-Hsiang Hsu Chih-Hao Huang Christian Hudon +Benoît Hudson Lawrence Hudson Michael Hudson Jim Hugunin diff --git a/Misc/NEWS.d/next/macOS/2019-08-23-12-14-34.bpo-37931.goYgQj.rst b/Misc/NEWS.d/next/macOS/2019-08-23-12-14-34.bpo-37931.goYgQj.rst new file mode 100644 index 00000000000..45b54e89cb8 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2019-08-23-12-14-34.bpo-37931.goYgQj.rst @@ -0,0 +1,3 @@ +Fixed a crash on OSX dynamic builds that occurred when re-initializing the +posix module after a Py_Finalize if the environment had changed since the +previous `import posix`. Patch by Benoît Hudson. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 89854711373..322c2159812 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1402,7 +1402,6 @@ win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) ** man environ(7). */ #include -static char **environ; #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) extern char **environ; #endif /* !_MSC_VER */ @@ -1420,15 +1419,16 @@ convertenviron(void) d = PyDict_New(); if (d == NULL) return NULL; -#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) - if (environ == NULL) - environ = *_NSGetEnviron(); -#endif #ifdef MS_WINDOWS /* _wenviron must be initialized in this way if the program is started through main() instead of wmain(). */ _wgetenv(L""); e = _wenviron; +#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) + /* environ is not accessible as an extern in a shared object on OSX; use + _NSGetEnviron to resolve it. The value changes if you add environment + variables between calls to Py_Initialize, so don't cache the value. */ + e = *_NSGetEnviron(); #else e = environ; #endif