diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 76812b71ba3..7310afc9958 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -264,6 +264,14 @@ def test_userptr_memory_leak(stdscr): if sys.getrefcount(obj) != nrefs: raise RuntimeError("set_userptr leaked references") +def test_userptr_segfault(stdscr): + panel = curses.panel.new_panel(stdscr) + class A: + def __del__(self): + panel.set_userptr(None) + panel.set_userptr(A()) + panel.set_userptr(None) + def test_resize_term(stdscr): if hasattr(curses, 'resizeterm'): lines, cols = curses.LINES, curses.COLS @@ -330,6 +338,7 @@ def main(stdscr): window_funcs(stdscr) test_userptr_without_set(stdscr) test_userptr_memory_leak(stdscr) + test_userptr_segfault(stdscr) test_resize_term(stdscr) test_issue6243(stdscr) test_unget_wch(stdscr) diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c index c11f3d84768..f5607028784 100644 --- a/Modules/_curses_panel.c +++ b/Modules/_curses_panel.c @@ -323,12 +323,17 @@ static PyObject * PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj) { PyObject *oldobj; + int rc; PyCursesInitialised; - oldobj = (PyObject *) panel_userptr(self->pan); - Py_XDECREF(oldobj); Py_INCREF(obj); - return PyCursesCheckERR(set_panel_userptr(self->pan, (void*)obj), - "set_panel_userptr"); + oldobj = (PyObject *) panel_userptr(self->pan); + rc = set_panel_userptr(self->pan, (void*)obj); + if (rc == ERR) { + /* In case of an ncurses error, decref the new object again */ + Py_DECREF(obj); + } + Py_XDECREF(oldobj); + return PyCursesCheckERR(rc, "set_panel_userptr"); } static PyObject *