fix: allow canvas area to exceed u16::MAX (#1891)
This allows Canvas grids where the width * height exceeds u16::MAX by converting values to usize earlier in several methods. Fixes: https://github.com/ratatui/ratatui/issues/1449
This commit is contained in:
@@ -128,7 +128,7 @@ impl BrailleGrid {
|
||||
/// Create a new `BrailleGrid` with the given width and height measured in terminal columns and
|
||||
/// rows respectively.
|
||||
fn new(width: u16, height: u16) -> Self {
|
||||
let length = usize::from(width * height);
|
||||
let length = usize::from(width) * usize::from(height);
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
@@ -156,7 +156,10 @@ impl Grid for BrailleGrid {
|
||||
}
|
||||
|
||||
fn paint(&mut self, x: usize, y: usize, color: Color) {
|
||||
let index = y / 4 * self.width as usize + x / 2;
|
||||
let index = y
|
||||
.saturating_div(4)
|
||||
.saturating_mul(self.width as usize)
|
||||
.saturating_add(x.saturating_div(2));
|
||||
// using get_mut here because we are indexing the vector with usize values
|
||||
// and we want to make sure we don't panic if the index is out of bounds
|
||||
if let Some(c) = self.utf16_code_points.get_mut(index) {
|
||||
@@ -190,7 +193,7 @@ impl CharGrid {
|
||||
/// Create a new `CharGrid` with the given width and height measured in terminal columns and
|
||||
/// rows respectively.
|
||||
fn new(width: u16, height: u16, cell_char: char) -> Self {
|
||||
let length = usize::from(width * height);
|
||||
let length = usize::from(width) * usize::from(height);
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
@@ -219,7 +222,7 @@ impl Grid for CharGrid {
|
||||
}
|
||||
|
||||
fn paint(&mut self, x: usize, y: usize, color: Color) {
|
||||
let index = y * self.width as usize + x;
|
||||
let index = y.saturating_mul(self.width as usize).saturating_add(x);
|
||||
// using get_mut here because we are indexing the vector with usize values
|
||||
// and we want to make sure we don't panic if the index is out of bounds
|
||||
if let Some(c) = self.cells.get_mut(index) {
|
||||
@@ -261,7 +264,7 @@ impl HalfBlockGrid {
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
pixels: vec![vec![Color::Reset; width as usize]; height as usize * 2],
|
||||
pixels: vec![vec![Color::Reset; width as usize]; (height as usize) * 2],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -937,4 +940,40 @@ mod tests {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// The canvas methods work a lot with arithmetic so here we enter various width and height
|
||||
// values to check if there are any integer overflows we just initialize the canvas painters
|
||||
#[test]
|
||||
fn check_canvas_paint_max() {
|
||||
let mut b_grid = BrailleGrid::new(u16::MAX, 2);
|
||||
let mut c_grid = CharGrid::new(u16::MAX, 2, 'd');
|
||||
|
||||
let max = u16::MAX as usize;
|
||||
|
||||
b_grid.paint(0, 0, Color::Red);
|
||||
b_grid.paint(0, max, Color::Red);
|
||||
b_grid.paint(max, 0, Color::Red);
|
||||
b_grid.paint(max, max, Color::Red);
|
||||
|
||||
c_grid.paint(0, 0, Color::Red);
|
||||
c_grid.paint(0, max, Color::Red);
|
||||
c_grid.paint(max, 0, Color::Red);
|
||||
c_grid.paint(max, max, Color::Red);
|
||||
}
|
||||
|
||||
// We delibately cause integer overflow to check if we don't panic and don't get weird behavior
|
||||
#[test]
|
||||
fn check_canvas_paint_overflow() {
|
||||
let mut b_grid = BrailleGrid::new(u16::MAX, 3);
|
||||
let mut c_grid = CharGrid::new(u16::MAX, 3, 'd');
|
||||
|
||||
let max = u16::MAX as usize + 10;
|
||||
|
||||
// see if we can paint outside bounds
|
||||
b_grid.paint(max, max, Color::Red);
|
||||
c_grid.paint(max, max, Color::Red);
|
||||
// see if we can paint usize max bounds
|
||||
b_grid.paint(usize::MAX, usize::MAX, Color::Red);
|
||||
c_grid.paint(usize::MAX, usize::MAX, Color::Red);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user