Fix use after free when dropping zerowidth data

Commit ec42b42ce6 added an optional
pointer for each cell, thus some old code that was optimizing copying
with 'ptr::copy' was duplicating "unique" pointers ('Box'), which was
resulting in use after free, after attempting to free both of these
pointers.

By replacing these unsafe blocks with safe Rust, the issue itself is
fixed and the potential for future memory problems is eliminated from
this area of the code.
This commit is contained in:
Kirill Chibisov 2020-11-13 05:22:28 +03:00 committed by GitHub
parent 7203f226fc
commit b6d94e7b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 12 additions and 20 deletions

View File

@ -1486,12 +1486,10 @@ impl<T: EventListener> Handler for Term<T> {
if self.mode.contains(TermMode::INSERT) && self.grid.cursor.point.col + width < num_cols { if self.mode.contains(TermMode::INSERT) && self.grid.cursor.point.col + width < num_cols {
let line = self.grid.cursor.point.line; let line = self.grid.cursor.point.line;
let col = self.grid.cursor.point.col; let col = self.grid.cursor.point.col;
let line = &mut self.grid[line]; let row = &mut self.grid[line][..];
let src = line[col..].as_ptr(); for col in (col.0..(num_cols - width).0).rev() {
let dst = line[(col + width)..].as_mut_ptr(); row.swap(col + width, col);
unsafe {
ptr::copy(src, dst, (num_cols - col - width).0);
} }
} }
@ -1574,18 +1572,15 @@ impl<T: EventListener> Handler for Term<T> {
let num_cells = (self.cols() - destination).0; let num_cells = (self.cols() - destination).0;
let line = cursor.point.line; let line = cursor.point.line;
let row = &mut self.grid[line]; let row = &mut self.grid[line][..];
unsafe { for offset in (0..num_cells).rev() {
let src = row[source..].as_ptr(); row.swap(destination.0 + offset, source.0 + offset);
let dst = row[destination..].as_mut_ptr();
ptr::copy(src, dst, num_cells);
} }
// Cells were just moved out toward the end of the line; // Cells were just moved out toward the end of the line;
// fill in between source and dest with blanks. // fill in between source and dest with blanks.
for cell in &mut row[source..destination] { for cell in &mut row[source.0..destination.0] {
*cell = bg.into(); *cell = bg.into();
} }
} }
@ -1841,21 +1836,18 @@ impl<T: EventListener> Handler for Term<T> {
let start = cursor.point.col; let start = cursor.point.col;
let end = min(start + count, cols - 1); let end = min(start + count, cols - 1);
let n = (cols - end).0; let num_cells = (cols - end).0;
let line = cursor.point.line; let line = cursor.point.line;
let row = &mut self.grid[line]; let row = &mut self.grid[line][..];
unsafe { for offset in 0..num_cells {
let src = row[end..].as_ptr(); row.swap(start.0 + offset, end.0 + offset);
let dst = row[start..].as_mut_ptr();
ptr::copy(src, dst, n);
} }
// Clear last `count` cells in the row. If deleting 1 char, need to delete // Clear last `count` cells in the row. If deleting 1 char, need to delete
// 1 cell. // 1 cell.
let end = cols - count; let end = (cols - count).0;
for cell in &mut row[end..] { for cell in &mut row[end..] {
*cell = bg.into(); *cell = bg.into();
} }