From 733ce196549696667e09eac8f83d844a5de4713e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 13 Apr 2024 20:45:39 -0700 Subject: [PATCH] terminal: handle case where eraseRowBounded happens at top of page Fixes #1677 If eraseRowBounded is called at the top of a page AND there is a tracked pin at the top of the page, then we'd have an integer overflow. The test case covers this and this adds a fix. --- src/terminal/PageList.zig | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index 6a159d463..1946a84aa 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -2107,7 +2107,14 @@ pub fn eraseRowBounded( const p = p_ptr.*; if (p.page == page and p.y >= pn.y and - p.y <= pn.y + limit) p.y -= 1; + p.y <= pn.y + limit) + { + if (p.y == 0) { + p.x = 0; + } else { + p.y -= 1; + } + } } return; @@ -2125,7 +2132,13 @@ pub fn eraseRowBounded( var pin_it = self.tracked_pins.keyIterator(); while (pin_it.next()) |p_ptr| { const p = p_ptr.*; - if (p.page == page and p.y >= pn.y) p.y -= 1; + if (p.page == page and p.y >= pn.y) { + if (p.y == 0) { + p.x = 0; + } else { + p.y -= 1; + } + } } } @@ -4481,6 +4494,26 @@ test "PageList eraseRowBounded less than full row" { try testing.expectEqual(@as(usize, 0), p_out.x); } +test "PageList eraseRowBounded with pin at top" { + const testing = std.testing; + const alloc = testing.allocator; + + var s = try init(alloc, 80, 10, null); + defer s.deinit(); + + // Pins + const p_top = try s.trackPin(s.pin(.{ .active = .{ .y = 0, .x = 5 } }).?); + defer s.untrackPin(p_top); + + // Erase only a few rows in our active + try s.eraseRowBounded(.{ .active = .{ .y = 0 } }, 3); + try testing.expectEqual(s.rows, s.totalRows()); + + try testing.expectEqual(s.pages.first.?, p_top.page); + try testing.expectEqual(@as(usize, 0), p_top.y); + try testing.expectEqual(@as(usize, 0), p_top.x); +} + test "PageList eraseRowBounded full rows single page" { const testing = std.testing; const alloc = testing.allocator;