From e68cc4508142ede537c623b73b9ae712159bbeb6 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 27 Nov 2024 17:15:32 +0100 Subject: [PATCH] Fix leaks in `gui_helper_3_helper_`. The facts are: * `PyTuple_SetItem` steals its third argument [1]. * `hocobj_new` returns a new reference. * `cpp2refstr` returns a new reference. In both cases the reason it leaks is that `hocobj_new` or `cpp2refstr` creates a new reference, then the reference count is increased once more. The once reference is stolen by `PyTuple_SetItem`; but there's still one INCREF which we can't pair up with a matching DECREF. [1]: https://docs.python.org/3.12/c-api/tuple.html#c.PyTuple_SetItem --- src/nrnpython/nrnpy_hoc.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index e3561a6413..6a86722976 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -2699,18 +2699,16 @@ static PyObject* gui_helper_3_helper_(const char* name, Object* obj, int handle_ auto active_obj = nb::steal(nrnpy_ho2po(*hoc_objgetarg(iiarg))); PyTuple_SetItem(args.ptr(), iarg + 3, active_obj.release().ptr()); } else if (hoc_is_pdouble_arg(iiarg)) { - PyHocObject* ptr_nrn = (PyHocObject*) hocobj_new(hocobject_type, 0, 0); + auto py_ptr = nb::steal(hocobj_new(hocobject_type, 0, 0)); + PyHocObject* ptr_nrn = (PyHocObject*) py_ptr.ptr(); ptr_nrn->type_ = PyHoc::HocScalarPtr; ptr_nrn->u.px_ = hoc_hgetarg(iiarg); - PyObject* py_ptr = (PyObject*) ptr_nrn; - Py_INCREF(py_ptr); - PyTuple_SetItem(args.ptr(), iarg + 3, py_ptr); + PyTuple_SetItem(args.ptr(), iarg + 3, py_ptr.release().ptr()); } else if (hoc_is_str_arg(iiarg)) { if (handle_strptr > 0) { char** str_arg = hoc_pgargstr(iiarg); - PyObject* py_ptr = cpp2refstr(str_arg); - Py_INCREF(py_ptr); - PyTuple_SetItem(args.ptr(), iarg + 3, py_ptr); + auto py_ptr = nb::steal(cpp2refstr(str_arg)); + PyTuple_SetItem(args.ptr(), iarg + 3, py_ptr.release().ptr()); } else { auto py_str = nb::steal(PyString_FromString(gargstr(iiarg))); PyTuple_SetItem(args.ptr(), iarg + 3, py_str.release().ptr());