Skip to content

Commit b01ca88

Browse files
committed
fix bdb: use slice copy in clear_all_file_breaks to avoid iterate-and-delete bug (gh-149015)
When multiple breakpoints share the same (filename, line), iterating the list directly while calling deleteMe() (which removes from the same list) causes the loop to skip alternate elements, leaving floor(N/2) orphan breakpoints. The fix (for bp in blist: → for bp in blist[:]:) matches the existing defensive pattern already used in clear_break() in the same file. Added regression test test_clear_all_file_breaks_with_multiple_bps_same_line.
1 parent 804c213 commit b01ca88

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

Lib/bdb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ def clear_all_file_breaks(self, filename):
747747
return 'There are no breakpoints in %s' % filename
748748
for line in self.breaks[filename]:
749749
blist = Breakpoint.bplist[filename, line]
750-
for bp in blist:
750+
for bp in blist[:]:
751751
bp.deleteMe()
752752
del self.breaks[filename]
753753
return None

Lib/test/test_bdb.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,23 @@ def test_next_to_botframe(self):
12321232

12331233

12341234
class TestRegressions(unittest.TestCase):
1235+
def test_clear_all_file_breaks_with_multiple_bps_same_line(self):
1236+
"""Regression test: gh-149015.
1237+
clear_all_file_breaks must remove all breakpoints even when
1238+
multiple breakpoints share the same (file, line)."""
1239+
dbg = Bdb()
1240+
src = canonic(__file__)
1241+
dbg.set_break(src, 10)
1242+
dbg.set_break(src, 10)
1243+
dbg.set_break(src, 10)
1244+
self.assertEqual(len(Breakpoint.bplist[(src, 10)]), 3)
1245+
dbg.clear_all_file_breaks(src)
1246+
self.assertNotIn((src, 10), Breakpoint.bplist)
1247+
for bp in list(Breakpoint.bpbynumber):
1248+
if bp is not None:
1249+
bp.deleteMe()
1250+
1251+
12351252
def test_format_stack_entry_no_lineno(self):
12361253
# See gh-101517
12371254
self.assertIn('Warning: lineno is None',

0 commit comments

Comments
 (0)