Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- `--strip-ansi`: also strip 8-bit C1 introducers (U+0090, U+0098, U+009B, U+009D, U+009E, U+009F) and DCS/SOS/PM/APC sequence bodies, which previously passed through. See #3729 (@curious-rabbit)
- Fix `--ignored-suffix` not falling back to first-line/shebang detection when the ignored suffix is also a registered extension (e.g. `--ignored-suffix .txt` on a shebang script), see #2745 and #3816 (@adnrivera)
- Fix `capacity overflow` panic when printing a snip separator at `--terminal-width=1` with multiple line ranges. Closes #3803, see #3804 (@leeewee)
- Fix `capacity overflow` panic when character-wrapping a line containing a character wider than `--terminal-width` with a painted background (e.g. `--highlight-line`). Closes #3844, see #3886 (@vjymisal0)
- Pass `--no-paging` to `bat` invocations inside the bash / zsh / fish / PowerShell shell completion scripts so that shell-level pager wiring (e.g. `LESSOPEN='|-bat -f -pp %s'`) cannot inject ANSI escape sequences into the completion candidates. Closes #3760 (@mvanhorn)
- Quote filenames before substituting them into `$LESSOPEN` / `$LESSCLOSE` templates, preventing shell injection when a filename contains shell metacharacters, see #3726 (@curious-rabbit)
- Fix `--list-themes` unconditionally probing the terminal via OSC 10/11 even when `--theme` was set to an explicit value, see #3700 (regression introduced in bc42149a). (@optimistiCli)
Expand Down
4 changes: 2 additions & 2 deletions src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ impl Printer for InteractivePrinter<'_> {
let text = self
.preprocess(text.trim_end_matches(['\r', '\n']), &mut cursor_total);

let mut max_width = cursor_max - cursor;
let mut max_width = cursor_max.saturating_sub(cursor);

// line buffer (avoid calling write! for every character)
let mut line_buf = String::with_capacity(max_width * 4);
Expand Down Expand Up @@ -965,7 +965,7 @@ impl Printer for InteractivePrinter<'_> {
write!(
handle,
"{}",
ansi_style.paint(" ".repeat(cursor_max - cursor))
ansi_style.paint(" ".repeat(cursor_max.saturating_sub(cursor)))
)?;
}
writeln!(handle)?;
Expand Down
18 changes: 18 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,24 @@ fn snip_at_terminal_width_one_does_not_panic() {
.success();
}

#[test]
fn wide_char_wrap_at_terminal_width_one_with_highlight_does_not_panic() {
// Regression test: a character wider than the terminal (e.g. a
// double-width emoji) combined with character wrapping and a painted
// background (via --highlight-line) used to make the cursor advance
// past `cursor_max`, causing `cursor_max - cursor` to underflow and
// `str::repeat` to abort with "capacity overflow".
bat()
.arg("--highlight-line=1")
.arg("--terminal-width=1")
.arg("--wrap=character")
.arg("--color=always")
.arg("--paging=never")
.write_stdin("\u{1F4E6}\u{1F4E6}\n")
.assert()
.success();
}

#[test]
fn line_range_multiple_with_context() {
bat()
Expand Down
Loading