From f719999950955a2fbcaaf80734c1a85696934d94 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 24 Mar 2024 14:46:43 -0700 Subject: [PATCH] terminal: add assertion to page integrity that row/col count > 0 --- src/terminal/PageList.zig | 12 +++++++---- src/terminal/page.zig | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index dd1543202..def46ee01 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -1976,13 +1976,17 @@ pub fn eraseRows( while (it.next()) |chunk| { // If the chunk is a full page, deinit thit page and remove it from // the linked list. - if (chunk.fullPage()) full_page: { + if (chunk.fullPage()) { // A rare special case is that we're deleting everything // in our linked list. erasePage requires at least one other - // page so to handle this we break out of this handling and - // do a normal row by row erase. + // page so to handle this we reinit this page, set it to zero + // size which will let us grow our active area back. if (chunk.page.next == null and chunk.page.prev == null) { - break :full_page; + const page = &chunk.page.data; + erased += page.size.rows; + page.reinit(); + page.size.rows = 0; + break; } self.erasePage(chunk.page); diff --git a/src/terminal/page.zig b/src/terminal/page.zig index 3fee11a0a..ea0192b33 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -175,7 +175,15 @@ pub const Page = struct { self.* = undefined; } + /// Reinitialize the page with the same capacity. + pub fn reinit(self: *Page) void { + @memset(self.memory, 0); + self.* = initBuf(OffsetBuf.init(self.memory), layout(self.capacity)); + } + pub const IntegrityError = error{ + ZeroRowCount, + ZeroColCount, UnmarkedGraphemeRow, MissingGraphemeData, InvalidGraphemeCount, @@ -212,6 +220,15 @@ pub const Page = struct { // used for the same reason as styles above. // + if (self.size.rows == 0) { + log.warn("page integrity violation zero row count", .{}); + return IntegrityError.ZeroRowCount; + } + if (self.size.cols == 0) { + log.warn("page integrity violation zero col count", .{}); + return IntegrityError.ZeroColCount; + } + var arena = ArenaAllocator.init(alloc_gpa); defer arena.deinit(); const alloc = arena.allocator(); @@ -1742,3 +1759,31 @@ test "Page verifyIntegrity styles ref count mismatch" { page.verifyIntegrity(testing.allocator), ); } + +test "Page verifyIntegrity zero rows" { + var page = try Page.init(.{ + .cols = 10, + .rows = 10, + .styles = 8, + }); + defer page.deinit(); + page.size.rows = 0; + try testing.expectError( + Page.IntegrityError.ZeroRowCount, + page.verifyIntegrity(testing.allocator), + ); +} + +test "Page verifyIntegrity zero cols" { + var page = try Page.init(.{ + .cols = 10, + .rows = 10, + .styles = 8, + }); + defer page.deinit(); + page.size.cols = 0; + try testing.expectError( + Page.IntegrityError.ZeroColCount, + page.verifyIntegrity(testing.allocator), + ); +}