Summary: | Use After Free when breakpoint is deleted from within breakpoint stop() python callback | ||
---|---|---|---|
Product: | gdb | Reporter: | k4lizen <k4lizen> |
Component: | python | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | vries |
Priority: | P2 | ||
Version: | HEAD | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
k4lizen
2024-12-06 12:34:55 UTC
This also works: repro.c ```c void stuff(){ // i dont do anything :7 } int main() { stuff(); } ``` This seems to works: ... diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 75f50e1f423..11c205d9dfb 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -1168,12 +1168,18 @@ gdbpy_breakpoint_cond_says_stop (const struct extension_langua ge_defn *extlang, gdbpy_enter enter_py (b->gdbarch); + /* Create a reference to the python object, keeping it alive in case the + breakpoint gets deleted in the stop method. */ + gdbpy_ref<> py_bp_ref = gdbpy_ref<>::new_reference (py_bp); + if (bp_obj->is_finish_bp) bpfinishpy_pre_stop_hook (bp_obj); if (PyObject_HasAttrString (py_bp, stop_func)) { gdbpy_ref<> result = gdbpy_call_method (py_bp, stop_func); + if (bp_obj->bp == nullptr) + error (_("Breakpoint deleted in %s.stop"), Py_TYPE (bp_obj)->tp_name); stop = 1; if (result != NULL) ... getting us: ... $ gdb -q -ex "source repro.py" -ex "run" ./repro Reading symbols from ./repro... Breakpoint 1 at 0x40049b: file repro.c, line 3. stuff break set Loaded. Starting program: /data/vries/gdb/repro [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Temporary breakpoint 2 at 0x4004b9: file repro.c, line 6. finish break set break hit Breakpoint deleted in EvilBreak.stop (gdb) ... |