diff options
author | Koichi Murase <myoga.murase@gmail.com> | 2019-08-07 07:59:16 +0900 |
---|---|---|
committer | Christian Duerr <contact@christianduerr.com> | 2019-08-06 22:59:16 +0000 |
commit | 33cfc52909bda1e2d5ceeae5397f254509d00539 (patch) | |
tree | 5c216e26de4c095058844cfab1ad18e7140157bd /alacritty_terminal/src | |
parent | b20d28578229a570b72f420fa50a64040bd2105b (diff) | |
download | alacritty-33cfc52909bda1e2d5ceeae5397f254509d00539.tar.gz alacritty-33cfc52909bda1e2d5ceeae5397f254509d00539.zip |
Ignore unsupported CSI sequences
Instead of ignoring unexpected intermediates in CSI escape sequences,
the intermediates are now explicitly checked and the escape sequence is
rejected when an unexpected intermediate is found.
Fixes #2171.
Diffstat (limited to 'alacritty_terminal/src')
-rw-r--r-- | alacritty_terminal/src/ansi.rs | 298 |
1 files changed, 160 insertions, 138 deletions
diff --git a/alacritty_terminal/src/ansi.rs b/alacritty_terminal/src/ansi.rs index b4cf4476..1914e952 100644 --- a/alacritty_terminal/src/ansi.rs +++ b/alacritty_terminal/src/ansi.rs @@ -890,11 +890,7 @@ where } #[inline] - fn csi_dispatch(&mut self, args: &[i64], intermediates: &[u8], _ignore: bool, action: char) { - let private = intermediates.get(0).map(|b| *b == b'?').unwrap_or(false); - let handler = &mut self.handler; - let writer = &mut self.writer; - + fn csi_dispatch(&mut self, args: &[i64], intermediates: &[u8], has_ignored_intermediates: bool, action: char) { macro_rules! unhandled { () => {{ debug!( @@ -913,12 +909,19 @@ where }; } - match action { - '@' => handler.insert_blank(Column(arg_or_default!(idx: 0, default: 1) as usize)), - 'A' => { + if has_ignored_intermediates || intermediates.len() > 1 { + unhandled!(); + } + + let handler = &mut self.handler; + let writer = &mut self.writer; + + match (action, intermediates.get(0)) { + ('@', None) => handler.insert_blank(Column(arg_or_default!(idx: 0, default: 1) as usize)), + ('A', None) => { handler.move_up(Line(arg_or_default!(idx: 0, default: 1) as usize)); }, - 'b' => { + ('b', None) => { if let Some(c) = self._state.preceding_char { for _ in 0..arg_or_default!(idx: 0, default: 1) { handler.input(c); @@ -927,13 +930,13 @@ where debug!("tried to repeat with no preceding char"); } }, - 'B' | 'e' => handler.move_down(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'c' => handler.identify_terminal(writer), - 'C' | 'a' => handler.move_forward(Column(arg_or_default!(idx: 0, default: 1) as usize)), - 'D' => handler.move_backward(Column(arg_or_default!(idx: 0, default: 1) as usize)), - 'E' => handler.move_down_and_cr(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'F' => handler.move_up_and_cr(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'g' => { + ('B', None) | ('e', None) => handler.move_down(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('c', None) => handler.identify_terminal(writer), + ('C', None) | ('a', None) => handler.move_forward(Column(arg_or_default!(idx: 0, default: 1) as usize)), + ('D', None) => handler.move_backward(Column(arg_or_default!(idx: 0, default: 1) as usize)), + ('E', None) => handler.move_down_and_cr(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('F', None) => handler.move_up_and_cr(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('g', None) => { let mode = match arg_or_default!(idx: 0, default: 0) { 0 => TabulationClearMode::Current, 3 => TabulationClearMode::All, @@ -942,14 +945,14 @@ where handler.clear_tabs(mode); }, - 'G' | '`' => handler.goto_col(Column(arg_or_default!(idx: 0, default: 1) as usize - 1)), - 'H' | 'f' => { + ('G', None) | ('`', None) => handler.goto_col(Column(arg_or_default!(idx: 0, default: 1) as usize - 1)), + ('H', None) | ('f', None) => { let y = arg_or_default!(idx: 0, default: 1) as usize; let x = arg_or_default!(idx: 1, default: 1) as usize; handler.goto(Line(y - 1), Column(x - 1)); }, - 'I' => handler.move_forward_tabs(arg_or_default!(idx: 0, default: 1)), - 'J' => { + ('I', None) => handler.move_forward_tabs(arg_or_default!(idx: 0, default: 1)), + ('J', None) => { let mode = match arg_or_default!(idx: 0, default: 0) { 0 => ClearMode::Below, 1 => ClearMode::Above, @@ -960,7 +963,7 @@ where handler.clear_screen(mode); }, - 'K' => { + ('K', None) => { let mode = match arg_or_default!(idx: 0, default: 0) { 0 => LineClearMode::Right, 1 => LineClearMode::Left, @@ -970,129 +973,68 @@ where handler.clear_line(mode); }, - 'S' => handler.scroll_up(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'T' => handler.scroll_down(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'L' => handler.insert_blank_lines(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'l' => { + ('S', None) => handler.scroll_up(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('T', None) => handler.scroll_down(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('L', None) => handler.insert_blank_lines(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('l', intermediate) => { + let is_private_mode = match intermediate { + Some(b'?') => true, + None => false, + _ => unhandled!(), + }; for arg in args { - let mode = Mode::from_primitive(private, *arg); + let mode = Mode::from_primitive(is_private_mode, *arg); match mode { Some(mode) => handler.unset_mode(mode), None => unhandled!(), } } }, - 'M' => handler.delete_lines(Line(arg_or_default!(idx: 0, default: 1) as usize)), - 'X' => handler.erase_chars(Column(arg_or_default!(idx: 0, default: 1) as usize)), - 'P' => handler.delete_chars(Column(arg_or_default!(idx: 0, default: 1) as usize)), - 'Z' => handler.move_backward_tabs(arg_or_default!(idx: 0, default: 1)), - 'd' => handler.goto_line(Line(arg_or_default!(idx: 0, default: 1) as usize - 1)), - 'h' => { + ('M', None) => handler.delete_lines(Line(arg_or_default!(idx: 0, default: 1) as usize)), + ('X', None) => handler.erase_chars(Column(arg_or_default!(idx: 0, default: 1) as usize)), + ('P', None) => handler.delete_chars(Column(arg_or_default!(idx: 0, default: 1) as usize)), + ('Z', None) => handler.move_backward_tabs(arg_or_default!(idx: 0, default: 1)), + ('d', None) => handler.goto_line(Line(arg_or_default!(idx: 0, default: 1) as usize - 1)), + ('h', intermediate) => { + let is_private_mode = match intermediate { + Some(b'?') => true, + None => false, + _ => unhandled!(), + }; for arg in args { - let mode = Mode::from_primitive(private, *arg); + let mode = Mode::from_primitive(is_private_mode, *arg); match mode { Some(mode) => handler.set_mode(mode), None => unhandled!(), } } }, - 'm' => { - // Sometimes a C-style for loop is just what you need - let mut i = 0; // C-for initializer + ('m', None) => { if args.is_empty() { handler.terminal_attribute(Attr::Reset); - return; - } - loop { - if i >= args.len() { - // C-for condition - break; + } else { + for attr in attrs_from_sgr_parameters(args) { + match attr { + Some(attr) => handler.terminal_attribute(attr), + None => unhandled!(), + } } - - let attr = match args[i] { - 0 => Attr::Reset, - 1 => Attr::Bold, - 2 => Attr::Dim, - 3 => Attr::Italic, - 4 => Attr::Underscore, - 5 => Attr::BlinkSlow, - 6 => Attr::BlinkFast, - 7 => Attr::Reverse, - 8 => Attr::Hidden, - 9 => Attr::Strike, - 21 => Attr::CancelBold, - 22 => Attr::CancelBoldDim, - 23 => Attr::CancelItalic, - 24 => Attr::CancelUnderline, - 25 => Attr::CancelBlink, - 27 => Attr::CancelReverse, - 28 => Attr::CancelHidden, - 29 => Attr::CancelStrike, - 30 => Attr::Foreground(Color::Named(NamedColor::Black)), - 31 => Attr::Foreground(Color::Named(NamedColor::Red)), - 32 => Attr::Foreground(Color::Named(NamedColor::Green)), - 33 => Attr::Foreground(Color::Named(NamedColor::Yellow)), - 34 => Attr::Foreground(Color::Named(NamedColor::Blue)), - 35 => Attr::Foreground(Color::Named(NamedColor::Magenta)), - 36 => Attr::Foreground(Color::Named(NamedColor::Cyan)), - 37 => Attr::Foreground(Color::Named(NamedColor::White)), - 38 => { - let mut start = 0; - if let Some(color) = parse_color(&args[i..], &mut start) { - i += start; - Attr::Foreground(color) - } else { - break; - } - }, - 39 => Attr::Foreground(Color::Named(NamedColor::Foreground)), - 40 => Attr::Background(Color::Named(NamedColor::Black)), - 41 => Attr::Background(Color::Named(NamedColor::Red)), - 42 => Attr::Background(Color::Named(NamedColor::Green)), - 43 => Attr::Background(Color::Named(NamedColor::Yellow)), - 44 => Attr::Background(Color::Named(NamedColor::Blue)), - 45 => Attr::Background(Color::Named(NamedColor::Magenta)), - 46 => Attr::Background(Color::Named(NamedColor::Cyan)), - 47 => Attr::Background(Color::Named(NamedColor::White)), - 48 => { - let mut start = 0; - if let Some(color) = parse_color(&args[i..], &mut start) { - i += start; - Attr::Background(color) - } else { - break; - } - }, - 49 => Attr::Background(Color::Named(NamedColor::Background)), - 90 => Attr::Foreground(Color::Named(NamedColor::BrightBlack)), - 91 => Attr::Foreground(Color::Named(NamedColor::BrightRed)), - 92 => Attr::Foreground(Color::Named(NamedColor::BrightGreen)), - 93 => Attr::Foreground(Color::Named(NamedColor::BrightYellow)), - 94 => Attr::Foreground(Color::Named(NamedColor::BrightBlue)), - 95 => Attr::Foreground(Color::Named(NamedColor::BrightMagenta)), - 96 => Attr::Foreground(Color::Named(NamedColor::BrightCyan)), - 97 => Attr::Foreground(Color::Named(NamedColor::BrightWhite)), - 100 => Attr::Background(Color::Named(NamedColor::BrightBlack)), - 101 => Attr::Background(Color::Named(NamedColor::BrightRed)), - 102 => Attr::Background(Color::Named(NamedColor::BrightGreen)), - 103 => Attr::Background(Color::Named(NamedColor::BrightYellow)), - 104 => Attr::Background(Color::Named(NamedColor::BrightBlue)), - 105 => Attr::Background(Color::Named(NamedColor::BrightMagenta)), - 106 => Attr::Background(Color::Named(NamedColor::BrightCyan)), - 107 => Attr::Background(Color::Named(NamedColor::BrightWhite)), - _ => unhandled!(), - }; - - handler.terminal_attribute(attr); - - i += 1; // C-for expr } }, - 'n' => handler.device_status(writer, arg_or_default!(idx: 0, default: 0) as usize), - 'r' => { - if private { - unhandled!(); - } + ('n', None) => handler.device_status(writer, arg_or_default!(idx: 0, default: 0) as usize), + ('q', Some(b' ')) => { + // DECSCUSR (CSI Ps SP q) -- Set Cursor Style + let style = match arg_or_default!(idx: 0, default: 0) { + 0 => None, + 1 | 2 => Some(CursorStyle::Block), + 3 | 4 => Some(CursorStyle::Underline), + 5 | 6 => Some(CursorStyle::Beam), + _ => unhandled!(), + }; + + handler.set_cursor_style(style); + }, + ('r', None) => { let arg0 = arg_or_default!(idx: 0, default: 1) as usize; let top = Line(arg0 - 1); // Bottom should be included in the range, but range end is not @@ -1104,19 +1046,8 @@ where handler.set_scrolling_region(top..bottom); }, - 's' => handler.save_cursor_position(), - 'u' => handler.restore_cursor_position(), - 'q' => { - let style = match arg_or_default!(idx: 0, default: 0) { - 0 => None, - 1 | 2 => Some(CursorStyle::Block), - 3 | 4 => Some(CursorStyle::Underline), - 5 | 6 => Some(CursorStyle::Beam), - _ => unhandled!(), - }; - - handler.set_cursor_style(style); - }, + ('s', None) => handler.save_cursor_position(), + ('u', None) => handler.restore_cursor_position(), _ => unhandled!(), } } @@ -1174,6 +1105,97 @@ where } } +fn attrs_from_sgr_parameters(parameters: &[i64]) -> Vec<Option<Attr>> { + // Sometimes a C-style for loop is just what you need + let mut i = 0; // C-for initializer + let mut attrs = Vec::with_capacity(parameters.len()); + loop { + if i >= parameters.len() { + // C-for condition + break; + } + + let attr = match parameters[i] { + 0 => Some(Attr::Reset), + 1 => Some(Attr::Bold), + 2 => Some(Attr::Dim), + 3 => Some(Attr::Italic), + 4 => Some(Attr::Underscore), + 5 => Some(Attr::BlinkSlow), + 6 => Some(Attr::BlinkFast), + 7 => Some(Attr::Reverse), + 8 => Some(Attr::Hidden), + 9 => Some(Attr::Strike), + 21 => Some(Attr::CancelBold), + 22 => Some(Attr::CancelBoldDim), + 23 => Some(Attr::CancelItalic), + 24 => Some(Attr::CancelUnderline), + 25 => Some(Attr::CancelBlink), + 27 => Some(Attr::CancelReverse), + 28 => Some(Attr::CancelHidden), + 29 => Some(Attr::CancelStrike), + 30 => Some(Attr::Foreground(Color::Named(NamedColor::Black))), + 31 => Some(Attr::Foreground(Color::Named(NamedColor::Red))), + 32 => Some(Attr::Foreground(Color::Named(NamedColor::Green))), + 33 => Some(Attr::Foreground(Color::Named(NamedColor::Yellow))), + 34 => Some(Attr::Foreground(Color::Named(NamedColor::Blue))), + 35 => Some(Attr::Foreground(Color::Named(NamedColor::Magenta))), + 36 => Some(Attr::Foreground(Color::Named(NamedColor::Cyan))), + 37 => Some(Attr::Foreground(Color::Named(NamedColor::White))), + 38 => { + let mut start = 0; + if let Some(color) = parse_color(¶meters[i..], &mut start) { + i += start; + Some(Attr::Foreground(color)) + } else { + None + } + }, + 39 => Some(Attr::Foreground(Color::Named(NamedColor::Foreground))), + 40 => Some(Attr::Background(Color::Named(NamedColor::Black))), + 41 => Some(Attr::Background(Color::Named(NamedColor::Red))), + 42 => Some(Attr::Background(Color::Named(NamedColor::Green))), + 43 => Some(Attr::Background(Color::Named(NamedColor::Yellow))), + 44 => Some(Attr::Background(Color::Named(NamedColor::Blue))), + 45 => Some(Attr::Background(Color::Named(NamedColor::Magenta))), + 46 => Some(Attr::Background(Color::Named(NamedColor::Cyan))), + 47 => Some(Attr::Background(Color::Named(NamedColor::White))), + 48 => { + let mut start = 0; + if let Some(color) = parse_color(¶meters[i..], &mut start) { + i += start; + Some(Attr::Background(color)) + } else { + None + } + }, + 49 => Some(Attr::Background(Color::Named(NamedColor::Background))), + 90 => Some(Attr::Foreground(Color::Named(NamedColor::BrightBlack))), + 91 => Some(Attr::Foreground(Color::Named(NamedColor::BrightRed))), + 92 => Some(Attr::Foreground(Color::Named(NamedColor::BrightGreen))), + 93 => Some(Attr::Foreground(Color::Named(NamedColor::BrightYellow))), + 94 => Some(Attr::Foreground(Color::Named(NamedColor::BrightBlue))), + 95 => Some(Attr::Foreground(Color::Named(NamedColor::BrightMagenta))), + 96 => Some(Attr::Foreground(Color::Named(NamedColor::BrightCyan))), + 97 => Some(Attr::Foreground(Color::Named(NamedColor::BrightWhite))), + 100 => Some(Attr::Background(Color::Named(NamedColor::BrightBlack))), + 101 => Some(Attr::Background(Color::Named(NamedColor::BrightRed))), + 102 => Some(Attr::Background(Color::Named(NamedColor::BrightGreen))), + 103 => Some(Attr::Background(Color::Named(NamedColor::BrightYellow))), + 104 => Some(Attr::Background(Color::Named(NamedColor::BrightBlue))), + 105 => Some(Attr::Background(Color::Named(NamedColor::BrightMagenta))), + 106 => Some(Attr::Background(Color::Named(NamedColor::BrightCyan))), + 107 => Some(Attr::Background(Color::Named(NamedColor::BrightWhite))), + _ => None, + }; + + attrs.push(attr); + + i += 1; // C-for expr + } + attrs +} + /// Parse a color specifier from list of attributes fn parse_color(attrs: &[i64], i: &mut usize) -> Option<Color> { if attrs.len() < 2 { |