1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-21 03:39:16 +03:00

Defend against crazy big images sent via iterm image protocol

This also handles a Nan case and allows us to survive term-crash-tests as of fb6fa3192a65e8862c3c743ba102f7e2af45b519

refs: https://github.com/wez/wezterm/issues/1031
This commit is contained in:
Wez Furlong 2021-08-16 23:42:40 -07:00
parent 7dd77a03da
commit 24d971c87d
4 changed files with 35 additions and 14 deletions

View File

@ -1,7 +1,8 @@
use crate::{Position, StableRowIndex, TerminalState};
use anyhow::Context;
use ordered_float::NotNan;
use std::sync::Arc;
use termwiz::cell::{Cell, CellAttributes};
use termwiz::cell::Cell;
use termwiz::image::{ImageCell, ImageDataType};
use termwiz::surface::change::ImageData;
use termwiz::surface::TextureCoordinate;
@ -57,7 +58,10 @@ pub enum ImageAttachStyle {
}
impl TerminalState {
pub(crate) fn assign_image_to_cells(&mut self, params: ImageAttachParams) -> PlacementInfo {
pub(crate) fn assign_image_to_cells(
&mut self,
params: ImageAttachParams,
) -> anyhow::Result<PlacementInfo> {
let seqno = self.seqno;
let physical_cols = self.screen().physical_cols;
let physical_rows = self.screen().physical_rows;
@ -81,10 +85,10 @@ impl TerminalState {
let first_row = self.screen().visible_row_to_stable_row(self.cursor.y);
let mut ypos =
NotNan::new(params.source_origin_y as f32 / params.image_height as f32).unwrap();
let start_xpos =
NotNan::new(params.source_origin_x as f32 / params.image_width as f32).unwrap();
let mut ypos = NotNan::new(params.source_origin_y as f32 / params.image_height as f32)
.context("computing ypos")?;
let start_xpos = NotNan::new(params.source_origin_x as f32 / params.image_width as f32)
.context("computing xpos")?;
let cursor_x = self.cursor.x;
let x_delta = (source_width as f32 / params.image_width as f32) / width_in_cells as f32;
@ -126,7 +130,7 @@ impl TerminalState {
.screen()
.get_cell(cursor_x + x, cursor_y)
.cloned()
.unwrap_or_else(|| Cell::new(' ', CellAttributes::default()));
.unwrap_or_else(Cell::blank);
let img = Box::new(ImageCell::with_z_index(
TextureCoordinate::new(xpos, ypos),
TextureCoordinate::new(xpos + x_delta, ypos + y_delta),
@ -171,11 +175,11 @@ impl TerminalState {
}
}
PlacementInfo {
Ok(PlacementInfo {
first_row,
rows: height_in_cells,
cols: width_in_cells,
}
})
}
/// cache recent images and avoid assigning a new id for repeated data!

View File

@ -50,6 +50,19 @@ impl TerminalState {
}
};
const MAX_IMAGE_SIZE: u32 = 100_000_000;
let size = info.width.saturating_mul(info.height).saturating_mul(4);
if size > MAX_IMAGE_SIZE {
log::error!(
"Ignoring iterm image data {}x{} because {} bytes > max allowed {}",
info.width,
info.height,
size,
MAX_IMAGE_SIZE
);
return;
}
// Figure out the dimensions.
let physical_cols = self.screen().physical_cols;
let physical_rows = self.screen().physical_rows;
@ -122,7 +135,7 @@ impl TerminalState {
};
let image_data = self.raw_image_to_image_data(data);
self.assign_image_to_cells(ImageAttachParams {
if let Err(err) = self.assign_image_to_cells(ImageAttachParams {
image_width: width as u32,
image_height: height as u32,
source_width: width as u32,
@ -139,6 +152,8 @@ impl TerminalState {
image_id: None,
placement_id: None,
do_not_move_cursor: false,
});
}) {
log::error!("set iterm2 image: {:#}", err);
}
}
}

View File

@ -127,7 +127,7 @@ impl TerminalState {
image_id: Some(image_id),
placement_id: placement.placement_id,
do_not_move_cursor: placement.do_not_move_cursor,
});
})?;
self.kitty_img
.placements

View File

@ -107,7 +107,7 @@ impl TerminalState {
let image_data = ImageDataType::new_single_frame(width, height, data);
let image_data = self.raw_image_to_image_data(image_data);
self.assign_image_to_cells(ImageAttachParams {
if let Err(err) = self.assign_image_to_cells(ImageAttachParams {
image_width: width,
image_height: height,
source_width: width,
@ -124,6 +124,8 @@ impl TerminalState {
image_id: None,
placement_id: None,
do_not_move_cursor: false,
});
}) {
log::error!("set sixel image: {:#}", err);
}
}
}