Author htgoebel
Recipients htgoebel
Date 2017-09-20.14:38:42
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1505918322.85.0.70670397569.issue31532@psf.upfronthosting.co.za>
In-reply-to
Content
When using

Py_GetPath();
Py_SetPath(pypath_w);

near the beginning of a program, Py_SetPath crashes with memory corruption if run on a systems with glibc's MALLOC_CHECK enabled.

The reason is: Py_GetPath and Py_SetPath use different memory interfaces.

* Py_GetPath() calls calculate_path(), which uses PyMem_New() to allocate the memory (see https://github.com/python/cpython/blob/v3.6.0/Modules/getpath.c#L738, assigned to `buf` first)

* But Py_SetPath() uses PyMem_RawFree() to free the memory (see https://github.com/python/cpython/blob/v3.6.0/Modules/getpath.c#L830).


This error DOES NOT occur on Windows, since for win32 there is a separate implementation, which uses PyMem_RawMalloc (see https://github.com/python/cpython/blob/v3.6.0/PC/getpathp.c#L378).

This error also DOES NOT occur in Python <= 3.5, since PYMEM_FUNCS have been the same as PYRAW_FUNCS (see https://github.com/python/cpython/blob/v3.5.0/Objects/obmalloc.c#L148). This was changed in v3.6.0: PYMEM_FUNCS now is PYOBJ_FUNCS, see https://github.com/python/cpython/blob/v3.6.0/Objects/obmalloc.c#L159.

This error only occurs when running on a system with glibc's MALLOC_CHECK enabled, which seems to be the default st least on CentOS, Fedora and ArchLinux.

Example code and relevant source see below.


Example stack trace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*** glibc detected *** ./dist/jcollect3: double free or corruption (out): 0x00007fde271ab030 ***
======= Backtrace: =========
/lib64/libc.so.6[0x37f0675e66]
/lib64/libc.so.6[0x37f06789b3]
/tmp/_MEIhKg3kx/libpython3.6m.so.1.0(Py_SetPath+0x15)[0x7fde2d20e825]
./dist/jcollect3[0x4043e2]
./dist/jcollect3[0x402db2]
./dist/jcollect3[0x402fb0]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x37f061ed5d]
./dist/jcollect3[0x401a9e]
======= Memory map: ========


How to reproduce
~~~~~~~~~~~~~~~~~~~~~~~~~

An example for this problem is the bootloader of PyInstaller (as of 2017-08-01).

* Make sure you are running on a Linux distribution having glibc's MALLOC_CHECK enabled.

* Set up a virtual environment (just too keep your system clean)

pip install https://github.com/pyinstaller/pyinstaller/archive/develop@%7B2017-08-01%7D.zip
echo 'print("Hello")' > test.py
pyinstaller test.py
dist/test/test  # run the frozen script

The relevant source of PyInstaller's bootloader is at <https://github.com/pyinstaller/pyinstaller/blob/develop@%7B2017-08-01%7D/bootloader/src/pyi_pythonlib.c#L466>
History
Date User Action Args
2017-09-20 14:38:42htgoebelsetrecipients: + htgoebel
2017-09-20 14:38:42htgoebelsetmessageid: <1505918322.85.0.70670397569.issue31532@psf.upfronthosting.co.za>
2017-09-20 14:38:42htgoebellinkissue31532 messages
2017-09-20 14:38:42htgoebelcreate