Skip to content

Commit

Permalink
fix(list): saturating_sub to fix highlight_symbol overflow (#949)
Browse files Browse the repository at this point in the history
An overflow (pedantically an underflow) can occur if the
highlight_symbol is a multi-byte char, and area is reduced to a size
less than that char length.
  • Loading branch information
mrjackwills committed Mar 16, 2024
1 parent 078e97e commit c56f49b
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions src/widgets/list.rs
Expand Up @@ -973,7 +973,7 @@ impl StatefulWidgetRef for List<'_> {
let highlight_symbol_width = self.highlight_symbol.unwrap_or("").width() as u16;
Rect {
x: row_area.x + highlight_symbol_width,
width: row_area.width - highlight_symbol_width,
width: row_area.width.saturating_sub(highlight_symbol_width),
..row_area
}
} else {
Expand Down Expand Up @@ -1046,7 +1046,7 @@ mod tests {
use std::borrow::Cow;

use pretty_assertions::assert_eq;
use rstest::rstest;
use rstest::{fixture, rstest};

use super::*;
use crate::{assert_buffer_eq, widgets::Borders};
Expand Down Expand Up @@ -2234,4 +2234,30 @@ mod tests {
" ",
]));
}

#[fixture]
fn single_line_buf() -> Buffer {
Buffer::empty(Rect::new(0, 0, 10, 1))
}

/// Regression test for a bug where highlight symbol being greater than width caused a panic due
/// to subtraction with underflow.
///
/// See [#949](https://github.com/ratatui-org/ratatui/pull/949) for details
#[rstest]
#[case::under(">>>>", "Item1", ">>>>Item1 ")] // enough space to render the highlight symbol
#[case::exact(">>>>>", "Item1", ">>>>>Item1")] // exact space to render the highlight symbol
#[case::overflow(">>>>>>", "Item1", ">>>>>>Item")] // not enough space
fn highlight_symbol_overflow(
#[case] highlight_symbol: &str,
#[case] item: &str,
#[case] expected: &str,
mut single_line_buf: Buffer,
) {
let list = List::new(vec![item]).highlight_symbol(highlight_symbol);
let mut state = ListState::default();
state.select(Some(0));
StatefulWidget::render(list, single_line_buf.area, &mut single_line_buf, &mut state);
assert_buffer_eq!(single_line_buf, Buffer::with_lines(vec![expected]));
}
}

0 comments on commit c56f49b

Please sign in to comment.