From 0aaedf4360ff3db1d724e148acc6f1c69d196c76 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 9 Jul 2026 19:55:13 -0700 Subject: [PATCH] terminal: saturate origin cursor offsets setCursorPos added origin-mode margins to requested row and column values before clamping them to the scrolling region. A request near maxInt(usize) overflowed during that addition and crashed instead of landing on the region boundary. Use saturating addition for the origin offsets. The existing clamp then places oversized requests on the bottom-right margin without changing normal cursor positioning. --- src/terminal/Terminal.zig | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index b9363684d..3bcfdf5d9 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -2120,8 +2120,8 @@ pub fn setCursorPos(self: *Terminal, row_req: usize, col_req: usize) void { // Calculate our new x/y const row = if (row_req == 0) 1 else row_req; const col = if (col_req == 0) 1 else col_req; - const x = @min(params.x_max, col + params.x_offset) -| 1; - const y = @min(params.y_max, row + params.y_offset) -| 1; + const x = @min(params.x_max, col +| params.x_offset) -| 1; + const y = @min(params.y_max, row +| params.y_offset) -| 1; // If the y is unchanged then this is fast pointer math if (y == self.screens.active.cursor.y) { @@ -3816,6 +3816,24 @@ fn clearDirty(t: *Terminal) void { t.screens.active.pages.clearDirty(); } +test "Terminal: setCursorPos saturates overflowing origin offsets" { + const alloc = testing.allocator; + var t = try init(alloc, .{ .cols = 10, .rows = 10 }); + defer t.deinit(alloc); + + t.scrolling_region = .{ + .top = 2, + .bottom = 7, + .left = 3, + .right = 8, + }; + t.modes.set(.origin, true); + + t.setCursorPos(std.math.maxInt(usize), std.math.maxInt(usize)); + try testing.expectEqual(@as(size.CellCountInt, 8), t.screens.active.cursor.x); + try testing.expectEqual(@as(size.CellCountInt, 7), t.screens.active.cursor.y); +} + test "Terminal: input with no control characters" { const alloc = testing.allocator; var t = try init(alloc, .{ .cols = 40, .rows = 40 });