From f9ded24b21b3343fa57247549b42b44217cca945 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Fri, 12 Jul 2024 12:22:44 +0200 Subject: [PATCH] fix(terminal): prevent escaping pane through scroll region (#3491) --- zellij-server/src/panes/grid.rs | 4 +- zellij-server/src/panes/unit/grid_tests.rs | 38 +++++++++++++++ ...id_tests__cannot_escape_scroll_region.snap | 47 +++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__cannot_escape_scroll_region.snap diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index c22cb480..781030b1 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -2745,7 +2745,9 @@ impl Perform for Grid { .next() .map(|param| param[0] as usize) .filter(|¶m| param != 0) - .map(|bottom| bottom.saturating_sub(1)); + .map(|bottom| { + std::cmp::min(self.height.saturating_sub(1), bottom.saturating_sub(1)) + }); self.set_scroll_region(top, bottom); if self.erasure_mode { self.move_cursor_to_line(top, EMPTY_TERMINAL_CHARACTER); diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs index 4b8b10c2..21c17b9e 100644 --- a/zellij-server/src/panes/unit/grid_tests.rs +++ b/zellij-server/src/panes/unit/grid_tests.rs @@ -3862,3 +3862,41 @@ fn text_ui_component_with_coordinates() { } assert_snapshot!(format!("{:?}", grid)); } + +#[test] +fn cannot_escape_scroll_region() { + // this tests a fix for a bug where it would be possible to set the scroll region bounds beyond + // the pane height, which would then allow a goto instruction beyond the scroll region to scape + // the pane bounds and render content on other panes + // + // what we do here is set the scroll region beyond the terminal bounds (`[1;42r` - whereas + // the terminal is just 41 lines high), and then issue a goto instruction to line 42, one line + // beyond the pane and scroll region bounds (`[42;1H`) and then print text `Hi there!`. + // This should be printed on the last line (zero indexed 40) of the terminal and not beyond it. + let mut vte_parser = vte::Parser::new(); + let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default())); + let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new())); + let debug = false; + let arrow_fonts = true; + let styled_underlines = true; + let explicitly_disable_kitty_keyboard_protocol = false; + let mut grid = Grid::new( + 41, + 120, + Rc::new(RefCell::new(Palette::default())), + terminal_emulator_color_codes, + Rc::new(RefCell::new(LinkHandler::new())), + Rc::new(RefCell::new(None)), + sixel_image_store, + Style::default(), + debug, + arrow_fonts, + styled_underlines, + explicitly_disable_kitty_keyboard_protocol, + ); + let content = "\u{1b}[1;42r\u{1b}[42;1HHi there!".as_bytes(); + for byte in content { + vte_parser.advance(&mut grid, *byte); + } + assert_snapshot!(format!("{:?}", grid)); +} diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__cannot_escape_scroll_region.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__cannot_escape_scroll_region.snap new file mode 100644 index 00000000..b2dcaaa7 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__cannot_escape_scroll_region.snap @@ -0,0 +1,47 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +assertion_line: 3894 +expression: "format!(\"{:?}\", grid)" +--- +00 (C): +01 (C): +02 (C): +03 (C): +04 (C): +05 (C): +06 (C): +07 (C): +08 (C): +09 (C): +10 (C): +11 (C): +12 (C): +13 (C): +14 (C): +15 (C): +16 (C): +17 (C): +18 (C): +19 (C): +20 (C): +21 (C): +22 (C): +23 (C): +24 (C): +25 (C): +26 (C): +27 (C): +28 (C): +29 (C): +30 (C): +31 (C): +32 (C): +33 (C): +34 (C): +35 (C): +36 (C): +37 (C): +38 (C): +39 (C): +40 (C): Hi there! +