fix: integer overflow crash when screen w * h > max(u16)

This commit is contained in:
CJ van den Berg 2024-12-03 19:33:35 +01:00 committed by Tim Culverhouse
parent 77f5795892
commit 5a8112b78b
5 changed files with 12 additions and 12 deletions

View file

@ -47,7 +47,7 @@ mouse_shape: MouseShape = .default,
/// sets each cell to the default cell
pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !InternalScreen {
var screen = InternalScreen{
.buf = try alloc.alloc(InternalCell, w * h),
.buf = try alloc.alloc(InternalCell, @as(usize, @intCast(w)) * h),
};
for (screen.buf, 0..) |_, i| {
screen.buf[i] = .{
@ -87,7 +87,7 @@ pub fn writeCell(
// height out of bounds
return;
}
const i = (row * self.width) + col;
const i = (@as(usize, @intCast(row)) * self.width) + col;
assert(i < self.buf.len);
self.buf[i].char.clearRetainingCapacity();
self.buf[i].char.appendSlice(cell.char.grapheme) catch {

View file

@ -33,7 +33,7 @@ pub fn init(alloc: std.mem.Allocator, winsize: Winsize, unicode: *const Unicode)
const w = winsize.cols;
const h = winsize.rows;
const self = Screen{
.buf = try alloc.alloc(Cell, w * h),
.buf = try alloc.alloc(Cell, @as(usize, @intCast(w)) * h),
.width = w,
.height = h,
.width_pix = winsize.x_pixel,
@ -53,7 +53,7 @@ pub fn writeCell(self: *Screen, col: u16, row: u16, cell: Cell) void {
if (col >= self.width or
row >= self.height)
return;
const i = (row * self.width) + col;
const i = (@as(usize, @intCast(row)) * self.width) + col;
assert(i < self.buf.len);
self.buf[i] = cell;
}
@ -62,7 +62,7 @@ pub fn readCell(self: *const Screen, col: u16, row: u16) ?Cell {
if (col >= self.width or
row >= self.height)
return null;
const i = (row * self.width) + col;
const i = (@as(usize, @intCast(row)) * self.width) + col;
assert(i < self.buf.len);
return self.buf[i];
}

View file

@ -315,7 +315,7 @@ pub fn queueRefresh(self: *Vaxis) void {
/// draws the screen to the terminal
pub fn render(self: *Vaxis, tty: AnyWriter) !void {
defer self.refresh = false;
assert(self.screen.buf.len == self.screen.width * self.screen.height); // correct size
assert(self.screen.buf.len == @as(usize, @intCast(self.screen.width)) * self.screen.height); // correct size
assert(self.screen.buf.len == self.screen_last.buf.len); // same size
// Set up sync before we write anything
@ -353,7 +353,7 @@ pub fn render(self: *Vaxis, tty: AnyWriter) !void {
if (self.caps.kitty_graphics)
try tty.writeAll(ctlseqs.kitty_graphics_clear);
var i: u16 = 0;
var i: usize = 0;
while (i < self.screen.buf.len) {
const cell = self.screen.buf[i];
const w: u16 = blk: {

View file

@ -198,16 +198,16 @@ pub fn fill(self: Window, cell: Cell) void {
self.screen.width < self.x_off or
self.screen.height < self.y_off)
return;
const first_row: u16 = @intCast(@max(self.y_off, 0));
const first_row: usize = @intCast(@max(self.y_off, 0));
if (self.x_off == 0 and self.width == self.screen.width) {
// we have a full width window, therefore contiguous memory.
const start = @min(first_row * self.width, self.screen.buf.len);
const end = @min(start + (self.height * self.width), self.screen.buf.len);
const end = @min(start + (@as(usize, @intCast(self.height)) * self.width), self.screen.buf.len);
@memset(self.screen.buf[start..end], cell);
} else {
// Non-contiguous. Iterate over rows an memset
var row: u16 = first_row;
const first_col: u16 = @max(self.x_off, 0);
var row: usize = first_row;
const first_col: usize = @max(self.x_off, 0);
const last_row = @min(self.height + self.y_off, self.screen.height);
while (row < last_row) : (row += 1) {
const start = @min(first_col + (row * self.screen.width), self.screen.buf.len);

View file

@ -95,7 +95,7 @@ csi_u_flags: vaxis.Key.KittyFlags = @bitCast(@as(u5, 0)),
/// sets each cell to the default cell
pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !Screen {
var screen = Screen{
.buf = try alloc.alloc(Cell, w * h),
.buf = try alloc.alloc(Cell, @as(usize, @intCast(w)) * h),
.scrolling_region = .{
.top = 0,
.bottom = h - 1,