test: add failing test for Screen.cursorAbsolute memory corruption

This commit is contained in:
Qwerasd
2024-12-25 18:58:42 -05:00
parent 7027147c76
commit b89e87c80d

View File

@ -3764,6 +3764,81 @@ test "Screen: cursorAbsolute across pages preserves style" {
}
}
test "Screen: cursorAbsolute to page with insufficient capacity" {
// This test checks for a very specific edge case
// which previously resulted in memory corruption.
//
// The conditions for this edge case are as such:
// - The cursor has an associated style or other managed memory.
// - The cursor moves to a different page.
// - The new page is at capacity and must have its capacity adjusted.
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 10, 3, 1);
defer s.deinit();
// Scroll down enough to go to another page
const start_page = &s.pages.pages.last.?.data;
const rem = start_page.capacity.rows;
start_page.pauseIntegrityChecks(true);
for (0..rem) |_| try s.cursorDownOrScroll();
start_page.pauseIntegrityChecks(false);
const new_page = &s.cursor.page_pin.node.data;
// We need our page to change for this test to make sense. If this
// assertion fails then the bug is in the test: we should be scrolling
// above enough for a new page to show up.
try testing.expect(start_page != new_page);
// Add styles to the start page until it reaches capacity.
{
// Pause integrity checks because they're slow and
// we're not testing this, this is just setup.
start_page.pauseIntegrityChecks(true);
defer start_page.pauseIntegrityChecks(false);
defer start_page.assertIntegrity();
var n: u24 = 1;
while (start_page.styles.add(
start_page.memory,
.{ .bg_color = .{ .rgb = @bitCast(n) } },
)) |_| n += 1 else |_| {}
}
// Set a style on the cursor.
try s.setAttribute(.{ .bold = {} });
{
const styleval = new_page.styles.get(
new_page.memory,
s.cursor.style_id,
);
try testing.expect(styleval.flags.bold);
}
// Go back up into the start page and we should still have that style.
s.cursorAbsolute(1, 1);
{
const cur_page = &s.cursor.page_pin.node.data;
// The page we're on now should NOT equal start_page, since its
// capacity should have been adjusted, which invalidates our ptr.
try testing.expect(start_page != cur_page);
// To make sure we DID change pages we check we're not on new_page.
try testing.expect(new_page != cur_page);
const styleval = cur_page.styles.get(
cur_page.memory,
s.cursor.style_id,
);
try testing.expect(styleval.flags.bold);
}
s.cursor.page_pin.node.data.assertIntegrity();
new_page.assertIntegrity();
}
test "Screen: scrolling" {
const testing = std.testing;
const alloc = testing.allocator;