mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
fix: add Contents.bgCell
to avoid accidentally indexing with undersized ints
This commit is contained in:
@ -2443,12 +2443,12 @@ fn updateCell(
|
|||||||
break :bg_alpha @intFromFloat(bg_alpha);
|
break :bg_alpha @intFromFloat(bg_alpha);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.cells.bg_cells[coord.y * self.cells.size.columns + coord.x] = .{
|
self.cells.bgCell(coord.y, coord.x).* = .{
|
||||||
rgb.r, rgb.g, rgb.b, bg_alpha,
|
rgb.r, rgb.g, rgb.b, bg_alpha,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cell.gridWidth() > 1 and coord.x < self.cells.size.columns - 1) {
|
if (cell.gridWidth() > 1 and coord.x < self.cells.size.columns - 1) {
|
||||||
self.cells.bg_cells[coord.y * self.cells.size.columns + coord.x + 1] = .{
|
self.cells.bgCell(coord.y, coord.x).* = .{
|
||||||
rgb.r, rgb.g, rgb.b, bg_alpha,
|
rgb.r, rgb.g, rgb.b, bg_alpha,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2645,11 +2645,11 @@ fn addPreeditCell(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add our opaque background cell
|
// Add our opaque background cell
|
||||||
self.cells.bg_cells[coord.y * self.cells.size.columns + coord.x] = .{
|
self.cells.bgCell(coord.y, coord.x).* = .{
|
||||||
bg.r, bg.g, bg.b, 255,
|
bg.r, bg.g, bg.b, 255,
|
||||||
};
|
};
|
||||||
if (cp.wide and coord.x < self.cells.size.columns - 1) {
|
if (cp.wide and coord.x < self.cells.size.columns - 1) {
|
||||||
self.cells.bg_cells[coord.y * self.cells.size.columns + coord.x + 1] = .{
|
self.cells.bgCell(coord.y, coord.x + 1).* = .{
|
||||||
bg.r, bg.g, bg.b, 255,
|
bg.r, bg.g, bg.b, 255,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,11 @@ pub const Contents = struct {
|
|||||||
size: renderer.GridSize = .{ .rows = 0, .columns = 0 },
|
size: renderer.GridSize = .{ .rows = 0, .columns = 0 },
|
||||||
|
|
||||||
/// Flat array containing cell background colors for the terminal grid.
|
/// Flat array containing cell background colors for the terminal grid.
|
||||||
/// Index with `bg_cells[y * size.columns + x]`.
|
///
|
||||||
|
/// Indexed as `bg_cells[row * size.columns + col]`.
|
||||||
|
///
|
||||||
|
/// Prefer accessing with `Contents.bgCell(row, col).*` instead
|
||||||
|
/// of directly indexing in order to avoid integer size bugs.
|
||||||
bg_cells: []mtl_shaders.CellBg = undefined,
|
bg_cells: []mtl_shaders.CellBg = undefined,
|
||||||
|
|
||||||
/// The ArrayListPool which holds all of the foreground cells. When sized
|
/// The ArrayListPool which holds all of the foreground cells. When sized
|
||||||
@ -167,6 +171,12 @@ pub const Contents = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Access a background cell. Prefer this function over direct indexing
|
||||||
|
/// of `bg_cells` in order to avoid integer size bugs causing overflows.
|
||||||
|
pub inline fn bgCell(self: *Contents, row: usize, col: usize) *mtl_shaders.CellBg {
|
||||||
|
return &self.bg_cells[row * self.size.columns + col];
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a cell to the appropriate list. Adding the same cell twice will
|
/// Add a cell to the appropriate list. Adding the same cell twice will
|
||||||
/// result in duplication in the vertex buffer. The caller should clear
|
/// result in duplication in the vertex buffer. The caller should clear
|
||||||
/// the corresponding row with Contents.clear to remove old cells first.
|
/// the corresponding row with Contents.clear to remove old cells first.
|
||||||
@ -197,7 +207,7 @@ pub const Contents = struct {
|
|||||||
pub fn clear(self: *Contents, y: terminal.size.CellCountInt) void {
|
pub fn clear(self: *Contents, y: terminal.size.CellCountInt) void {
|
||||||
assert(y < self.size.rows);
|
assert(y < self.size.rows);
|
||||||
|
|
||||||
@memset(self.bg_cells[y * self.size.columns ..][0..self.size.columns], .{ 0, 0, 0, 0 });
|
@memset(self.bg_cells[@as(usize, y) * self.size.columns ..][0..self.size.columns], .{ 0, 0, 0, 0 });
|
||||||
|
|
||||||
// We have a special list containing the cursor cell at the start
|
// We have a special list containing the cursor cell at the start
|
||||||
// of our fg row pool, so we need to add 1 to the y to get the
|
// of our fg row pool, so we need to add 1 to the y to get the
|
||||||
@ -221,7 +231,7 @@ test Contents {
|
|||||||
for (0..rows) |y| {
|
for (0..rows) |y| {
|
||||||
try testing.expect(c.fg_rows.lists[y + 1].items.len == 0);
|
try testing.expect(c.fg_rows.lists[y + 1].items.len == 0);
|
||||||
for (0..cols) |x| {
|
for (0..cols) |x| {
|
||||||
try testing.expectEqual(.{0, 0, 0, 0}, c.bg_cells[y * cols + x]);
|
try testing.expectEqual(.{0, 0, 0, 0}, c.bgCell(y, x).*);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// And the cursor row should have a capacity of 1 and also be empty.
|
// And the cursor row should have a capacity of 1 and also be empty.
|
||||||
@ -235,9 +245,9 @@ test Contents {
|
|||||||
.grid_pos = .{ 4, 1 },
|
.grid_pos = .{ 4, 1 },
|
||||||
.color = .{ 0, 0, 0, 1 },
|
.color = .{ 0, 0, 0, 1 },
|
||||||
};
|
};
|
||||||
c.bg_cells[1 * cols + 4] = bg_cell;
|
c.bgCell(1, 4).* = bg_cell;
|
||||||
try c.add(alloc, .text, fg_cell);
|
try c.add(alloc, .text, fg_cell);
|
||||||
try testing.expectEqual(bg_cell, c.bg_cells[1 * cols + 4]);
|
try testing.expectEqual(bg_cell, c.bgCell(1, 4).*);
|
||||||
// The fg row index is offset by 1 because of the cursor list.
|
// The fg row index is offset by 1 because of the cursor list.
|
||||||
try testing.expectEqual(fg_cell, c.fg_rows.lists[2].items[0]);
|
try testing.expectEqual(fg_cell, c.fg_rows.lists[2].items[0]);
|
||||||
|
|
||||||
@ -246,7 +256,7 @@ test Contents {
|
|||||||
for (0..rows) |y| {
|
for (0..rows) |y| {
|
||||||
try testing.expect(c.fg_rows.lists[y + 1].items.len == 0);
|
try testing.expect(c.fg_rows.lists[y + 1].items.len == 0);
|
||||||
for (0..cols) |x| {
|
for (0..cols) |x| {
|
||||||
try testing.expectEqual(.{0, 0, 0, 0}, c.bg_cells[y * cols + x]);
|
try testing.expectEqual(.{0, 0, 0, 0}, c.bgCell(y, x).*);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +293,7 @@ test "Contents clear retains other content" {
|
|||||||
.grid_pos = .{ 4, 1 },
|
.grid_pos = .{ 4, 1 },
|
||||||
.color = .{ 0, 0, 0, 1 },
|
.color = .{ 0, 0, 0, 1 },
|
||||||
};
|
};
|
||||||
c.bg_cells[1 * cols + 4] = bg_cell_1;
|
c.bgCell(1, 4).* = bg_cell_1;
|
||||||
try c.add(alloc, .text, fg_cell_1);
|
try c.add(alloc, .text, fg_cell_1);
|
||||||
// bg and fg cells in row 2
|
// bg and fg cells in row 2
|
||||||
const bg_cell_2: mtl_shaders.CellBg = .{ 0, 0, 0, 1 };
|
const bg_cell_2: mtl_shaders.CellBg = .{ 0, 0, 0, 1 };
|
||||||
@ -292,14 +302,14 @@ test "Contents clear retains other content" {
|
|||||||
.grid_pos = .{ 4, 2 },
|
.grid_pos = .{ 4, 2 },
|
||||||
.color = .{ 0, 0, 0, 1 },
|
.color = .{ 0, 0, 0, 1 },
|
||||||
};
|
};
|
||||||
c.bg_cells[2 * cols + 4] = bg_cell_2;
|
c.bgCell(2, 4).* = bg_cell_2;
|
||||||
try c.add(alloc, .text, fg_cell_2);
|
try c.add(alloc, .text, fg_cell_2);
|
||||||
|
|
||||||
// Clear row 1, this should leave row 2 untouched
|
// Clear row 1, this should leave row 2 untouched
|
||||||
c.clear(1);
|
c.clear(1);
|
||||||
|
|
||||||
// Row 2 should still contain its cells.
|
// Row 2 should still contain its cells.
|
||||||
try testing.expectEqual(bg_cell_2, c.bg_cells[2 * cols + 4]);
|
try testing.expectEqual(bg_cell_2, c.bgCell(2, 4).*);
|
||||||
// Fg row index is +1 because of cursor list at start
|
// Fg row index is +1 because of cursor list at start
|
||||||
try testing.expectEqual(fg_cell_2, c.fg_rows.lists[3].items[0]);
|
try testing.expectEqual(fg_cell_2, c.fg_rows.lists[3].items[0]);
|
||||||
}
|
}
|
||||||
@ -323,7 +333,7 @@ test "Contents clear last added content" {
|
|||||||
.grid_pos = .{ 4, 1 },
|
.grid_pos = .{ 4, 1 },
|
||||||
.color = .{ 0, 0, 0, 1 },
|
.color = .{ 0, 0, 0, 1 },
|
||||||
};
|
};
|
||||||
c.bg_cells[1 * cols + 4] = bg_cell_1;
|
c.bgCell(1, 4).* = bg_cell_1;
|
||||||
try c.add(alloc, .text, fg_cell_1);
|
try c.add(alloc, .text, fg_cell_1);
|
||||||
// bg and fg cells in row 2
|
// bg and fg cells in row 2
|
||||||
const bg_cell_2: mtl_shaders.CellBg = .{ 0, 0, 0, 1 };
|
const bg_cell_2: mtl_shaders.CellBg = .{ 0, 0, 0, 1 };
|
||||||
@ -332,14 +342,14 @@ test "Contents clear last added content" {
|
|||||||
.grid_pos = .{ 4, 2 },
|
.grid_pos = .{ 4, 2 },
|
||||||
.color = .{ 0, 0, 0, 1 },
|
.color = .{ 0, 0, 0, 1 },
|
||||||
};
|
};
|
||||||
c.bg_cells[2 * cols + 4] = bg_cell_2;
|
c.bgCell(2, 4).* = bg_cell_2;
|
||||||
try c.add(alloc, .text, fg_cell_2);
|
try c.add(alloc, .text, fg_cell_2);
|
||||||
|
|
||||||
// Clear row 2, this should leave row 1 untouched
|
// Clear row 2, this should leave row 1 untouched
|
||||||
c.clear(2);
|
c.clear(2);
|
||||||
|
|
||||||
// Row 1 should still contain its cells.
|
// Row 1 should still contain its cells.
|
||||||
try testing.expectEqual(bg_cell_1, c.bg_cells[1 * cols + 4]);
|
try testing.expectEqual(bg_cell_1, c.bgCell(1, 4).*);
|
||||||
// Fg row index is +1 because of cursor list at start
|
// Fg row index is +1 because of cursor list at start
|
||||||
try testing.expectEqual(fg_cell_1, c.fg_rows.lists[2].items[0]);
|
try testing.expectEqual(fg_cell_1, c.fg_rows.lists[2].items[0]);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user