]> granicus.if.org Git - python/commitdiff
#18113: avoid segfault if Py_XDECREF triggers code that calls set_panel_userptr again
authorAndrew Kuchling <amk@amk.ca>
Sat, 22 Jun 2013 18:50:56 +0000 (14:50 -0400)
committerAndrew Kuchling <amk@amk.ca>
Sat, 22 Jun 2013 18:50:56 +0000 (14:50 -0400)
Problem noted & original patch by Serhiy Storchaka; I tweaked the patch a bit.

Lib/test/test_curses.py
Modules/_curses_panel.c

index 76812b71ba3ba31c1c741920841d93e3c7898765..7310afc9958f91a99f6fe62c8bd69394d44dcedb 100644 (file)
@@ -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)
index c11f3d8476802636a50b9f09e14735aeb33925a8..f5607028784755fc57dc667a3c0b6f985ef2e78c 100644 (file)
@@ -323,12 +323,17 @@ static PyObject *
 PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj)
 {
     PyObject *oldobj;
+    int rc;
     PyCursesInitialised;
+    Py_INCREF(obj);
     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);
-    Py_INCREF(obj);
-    return PyCursesCheckERR(set_panel_userptr(self->pan, (void*)obj),
-                            "set_panel_userptr");
+    return PyCursesCheckERR(rc, "set_panel_userptr");
 }
 
 static PyObject *