The following function, compiled and linked into a shared library, segfaults when called from Python:
```
#define PY_SSIZE_T_CLEAN
#include <Python.h>
extern "C" PyObject* my_func() {
return Py_BuildValue("(O)", Py_None);
}
```
called using ctypes:
```
from ctypes import CDLL
h = CDLL('./libtest.so’)
h.my_func()”
```
crashes with a stacktrace
```
Program received signal SIGSEGV, Segmentation fault.
_PyObject_GC_TRACK_impl (filename=0x7fffed7ab1b0 "src/Objects/tupleobject.c", lineno=36, op=(0x0,)) at src/Include/internal/pycore_object.h:43
(gdb) bt
#0 _PyObject_GC_TRACK_impl (filename=0x7fffed7ab1b0 "src/Objects/tupleobject.c", lineno=36,
op=(0x0,)) at src/Include/internal/pycore_object.h:43
#1 tuple_gc_track (op=0x7fffe5e42dc0) at src/Objects/tupleobject.c:36
#2 PyTuple_New (size=<optimized out>) at src/Objects/tupleobject.c:124
#3 PyTuple_New (size=size@entry=1) at src/Objects/tupleobject.c:100
#4 0x00007fffed7031eb in do_mktuple (p_format=0x7fffffffa8d0, p_va=0x7fffffffa8d8, endchar=<optimized out>, n=1, flags=1) at src/Python/modsupport.c:259
#5 0x00007fffed703358 in va_build_value (format=<optimized out>, va=va@entry=0x7fffffffa918, flags=flags@entry=1) at src/Python/modsupport.c:562
#6 0x00007fffed7036d9 in _Py_BuildValue_SizeT (format=<optimized out>) at src/Python/modsupport.c:530
#7 0x00007fffedae6126 in my_func () at test.cpp:4
#8 0x00007fffedaf1c9d in ffi_call_unix64 () from libffi.so.7
#9 0x00007fffedaf0623 in ffi_call_int () from libffi.so.7
…
```
this is reproducible on RHEL7 (Python 3.9.7 built with GCC 11.2) and macOS (Python 3.9.10, 3.10.2 and 3.11.0a4 installed via MacPorts).
It does not crash with Python 3.8, I tested on RHEL7 (Python 3.8.3 built with GCC 9.3.0) and macOS (Python 3.8.12 installed via MacPorts).
This is meant to be a minimal example. It seems to be important that `Py_BuildValue` is returning a tuple, but the size of that tuple is not important.
`"O"` and `Py_None` are also not important, it still crashes with `"i"` and `42`.
The definition of `PY_SSIZE_T_CLEAN` also does not seem to be important; the only obvious difference it makes is whether I see `_Py_BuildValue_SizeT` or `Py_BuildValue` in the backtrace.
This seems to be a bit of an unlikely bug, so apologies in advance if I have missed something obvious. I tried to be thorough, but I do not have a lot of experience working with the Python C API.
|