From b99fda521447e38b4ca800d20e93e3bd2250517f Mon Sep 17 00:00:00 2001 From: Michael Brumlow Date: Tue, 10 Jan 2017 00:05:26 -0600 Subject: Fixing panic on cat /dev/urandom - Checks to make sure lines count coming from the pty are within a proper range before doing scrolling. - Sanitizes scroll region when being set. - Changes panic for unimplemented screen clear to a print statement. The first two changes ensure scrolling won't crash us. By sanitizing the region on set we don't have to complicate the scroll code with limits, mins, or maxes to ensure the scroll operation is within the range. Checking if the lines is greater than the total region allows us to simply clear the region and avoid subtracting large numbers from small ones. --- src/term/mod.rs | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/term/mod.rs b/src/term/mod.rs index 47d30d3f..4cb0c815 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -567,6 +567,7 @@ impl Term { /// Scroll screen down /// /// Text moves down; clear at bottom + /// Expects origin to be in scroll range. #[inline] fn scroll_down_relative(&mut self, origin: Line, lines: Line) { debug_println!("scroll_down: {}", lines); @@ -574,18 +575,24 @@ impl Term { // Copy of cell template; can't have it borrowed when calling clear/scroll let template = self.empty_cell; + // Clear the entire region if lines is going to be greater than the region. + // This also ensures all the math below this if statement is sane. + if lines > self.scroll_region.end - origin { + self.grid.clear_region(origin..self.scroll_region.end, |c| c.reset(&template)); + return; + } + // Clear `lines` lines at bottom of area { let end = self.scroll_region.end; - let start = limit(end - lines, Line(0), self.scroll_region.end); + let start = end - lines; self.grid.clear_region(start..end, |c| c.reset(&template)); } // Scroll between origin and bottom { let end = self.scroll_region.end; - let start = limit(origin + lines, Line(0), self.scroll_region.end); - let lines = limit(lines, Line(0), self.grid.num_lines()); + let start = origin + lines; self.grid.scroll_down(start..end, lines); } } @@ -593,6 +600,7 @@ impl Term { /// Scroll screen up /// /// Text moves up; clear at top + /// Expects origin to be in scroll range. #[inline] fn scroll_up_relative(&mut self, origin: Line, lines: Line) { debug_println!("scroll_up: {}", lines); @@ -600,19 +608,23 @@ impl Term { // Copy of cell template; can't have it borrowed when calling clear/scroll let template = self.empty_cell; + // Clear the entire region if lines is going to be greater than the region. + // This also ensures all the math below this if statement is sane. + if lines > self.scroll_region.end - origin { + self.grid.clear_region(origin..self.scroll_region.end, |c| c.reset(&template)); + return; + } + // Clear `lines` lines starting from origin to origin + lines - { - let start = limit(origin, Line(0), self.grid.num_lines() - 1); - let end = limit(start + lines, Line(0), self.grid.num_lines() - 1); - self.grid.clear_region(start..end, |c| c.reset(&template)); + { + let end = origin + lines; + self.grid.clear_region(origin..end, |c| c.reset(&template)); } // Scroll from origin to bottom less number of lines { - let start = limit(origin, Line(0), self.grid.num_lines() - 1); - let end = limit(self.scroll_region.end - lines, Line(0), self.grid.num_lines() - 1); - let lines = limit(lines, Line(0), self.grid.num_lines()); - self.grid.scroll_up(start..end, lines); + let end = self.scroll_region.end - lines; + self.grid.scroll_up(origin..end, lines); } } } @@ -968,7 +980,7 @@ impl ansi::Handler for Term { self.grid.clear(|c| c.reset(&template)); }, _ => { - panic!("ansi::ClearMode::Above not implemented"); + err_println!("ansi::ClearMode::Above not implemented"); } } } @@ -1057,7 +1069,8 @@ impl ansi::Handler for Term { #[inline] fn set_scrolling_region(&mut self, region: Range) { debug_println!("set scroll region: {:?}", region); - self.scroll_region = region; + self.scroll_region.start = min(region.start, self.grid.num_lines()); + self.scroll_region.end = min(region.end, self.grid.num_lines()); self.goto(Line(0), Column(0)); } -- cgit v1.2.3-54-g00ecf From 6656df1401a01aea67d1ffb3be032075c05d740f Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Mon, 9 Jan 2017 23:09:11 -0800 Subject: Fix last panic with `cat /dev/urandom` --- src/term/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/term/mod.rs b/src/term/mod.rs index 4cb0c815..cc1715a9 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -1002,7 +1002,7 @@ impl ansi::Handler for Term { if self.cursor.line == self.scroll_region.start { self.scroll_down(Line(1)); } else { - self.cursor.line -= 1; + self.cursor.line -= min(self.cursor.line, Line(1)); } } -- cgit v1.2.3-54-g00ecf