vtparse: recognize utf8 encoded c1 codes in more cases

There were two bugs here:

* \u8D (the utf8 encoded representation of 0x8d, aka: RI) was not
  recognized as a C1 code and was instead passed through as printable
  text.
* The \u8D is a zero-width sequence which means that a subsequent
  set_cell call on the new empty-by-default line wouldn't allocate
  any cells in the line array, and the assigment to the line would
  panic.

This commit avoids the panic for the second case, and then fixes up
the vtparser to correctly recognize the sequence as a C1 control.

refs: https://github.com/wez/wezterm/issues/768
This commit is contained in:
Wez Furlong 2021-05-08 00:39:29 -07:00
parent 9a1314c5b1
commit ff153ba27f
4 changed files with 28 additions and 4 deletions

View File

@ -13,6 +13,7 @@ As features stabilize some brief notes about them will accumulate here.
* Fixed: ssh client would read `/etc/ssh/config` rather than the proper `/etc/ssh/ssh_config`
* x11: support for [VoidSymbol](config/keys.md#voidsymbol) in key assignments. Thanks to [@digitallyserviced](https://github.com/digitallyserviced)! [#759](https://github.com/wez/wezterm/pull/759)
* Fixed: UTF8-encoded-C1 control codes were not always recognized as control codes, and could result in a panic when later attempting to update the line. [#768](https://github.com/wez/wezterm/issues/768)
### 20210502-154244-3f7122cb

View File

@ -789,6 +789,13 @@ fn test_scrollup() {
assert_eq!(term.screen().visible_row_to_stable_row(0), 7);
}
#[test]
fn test_ri() {
let mut term = TestTerm::new(3, 1, 10);
term.print("1\n\u{8d}\n");
assert_all_contents(&term, file!(), line!(), &["1", "", ""]);
}
#[test]
fn test_scroll_margins() {
let mut term = TestTerm::new(3, 1, 10);

View File

@ -305,9 +305,15 @@ impl Line {
pub fn set_cell(&mut self, idx: usize, cell: Cell) -> &Cell {
let width = cell.width();
// if the line isn't wide enough, pad it out with the default attributes
if idx + width >= self.cells.len() {
self.cells.resize(idx + width, Cell::default());
// if the line isn't wide enough, pad it out with the default attributes.
// The .max(1) stuff is here in case we get called with a
// zero-width cell. That shouldn't happen: those sequences
// should get filtered out in the terminal parsing layer,
// but in case one does sneak through, we need to ensure that
// we grow the cells array to hold this bogus entry.
// https://github.com/wez/wezterm/issues/768
if idx + width.max(1) >= self.cells.len() {
self.cells.resize(idx + width.max(1), Cell::default());
}
self.invalidate_implicit_hyperlinks();

View File

@ -622,7 +622,9 @@ impl VTParser {
let byte = ((c as u32) & 0xff) as u8;
let (action, state) = lookup(self.utf8_return_state, byte);
if state != self.utf8_return_state && state != State::Utf8Sequence {
if action == Action::Execute
|| (state != self.utf8_return_state && state != State::Utf8Sequence)
{
self.action(lookup_exit(self.utf8_return_state), 0, actor);
self.action(action, byte, actor);
self.action(lookup_entry(state), 0, actor);
@ -941,6 +943,14 @@ mod test {
);
}
#[test]
fn utf8_control() {
assert_eq!(
parse_as_vec("\u{8d}".as_bytes()),
vec![VTAction::ExecuteC0orC1(0x8d)]
);
}
#[test]
fn tmux_control() {
assert_eq!(