aboutsummaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/ansi.rs
diff options
context:
space:
mode:
authorKoichi Murase <myoga.murase@gmail.com>2019-08-07 07:59:16 +0900
committerChristian Duerr <contact@christianduerr.com>2019-08-06 22:59:16 +0000
commit33cfc52909bda1e2d5ceeae5397f254509d00539 (patch)
tree5c216e26de4c095058844cfab1ad18e7140157bd /alacritty_terminal/src/ansi.rs
parentb20d28578229a570b72f420fa50a64040bd2105b (diff)
downloadalacritty-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/ansi.rs')
-rw-r--r--alacritty_terminal/src/ansi.rs298
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(&parameters[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(&parameters[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 {