From 9150507209fd60a4eeb6374f7aabd3f1226f150f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 3 Feb 2022 19:20:41 +0100 Subject: [PATCH] sixel: resize: truncate instead of failing, when new size exceeds max size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the size we’re trying to set exceeds the configured max size, truncate instead of failing. --- CHANGELOG.md | 2 ++ sixel.c | 32 +++++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b3b95c7..1a75036b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -120,6 +120,8 @@ (https://codeberg.org/dnkl/foot/issues/883). * Bash completion giving an error when completing a list of short options +* Sixel: large image resizes (triggered by e.g. large repeat counts in + `DECGRI`) are now truncated instead of ignored. ### Security diff --git a/sixel.c b/sixel.c index b659a3c0..335700c5 100644 --- a/sixel.c +++ b/sixel.c @@ -1104,7 +1104,7 @@ sixel_unhook(struct terminal *term) render_refresh(term); } -static bool +static void resize_horizontally(struct terminal *term, int new_width) { LOG_DBG("resizing image horizontally: %dx(%d) -> %dx(%d)", @@ -1112,10 +1112,13 @@ resize_horizontally(struct terminal *term, int new_width) new_width, term->sixel.image.height); if (unlikely(new_width > term->sixel.max_width)) { - LOG_WARN("maximum image dimensions reached"); - return false; + LOG_WARN("maximum image dimensions exceeded, truncating"); + new_width = term->sixel.max_width; } + if (unlikely(term->sixel.image.width == new_width)) + return; + uint32_t *old_data = term->sixel.image.data; const int old_width = term->sixel.image.width; const int height = term->sixel.image.height; @@ -1145,7 +1148,6 @@ resize_horizontally(struct terminal *term, int new_width) term->sixel.image.data = new_data; term->sixel.image.width = new_width; term->sixel.row_byte_ofs = term->sixel.pos.row * new_width; - return true; } static bool @@ -1197,11 +1199,14 @@ resize(struct terminal *term, int new_width, int new_height) term->sixel.image.width, term->sixel.image.height, new_width, new_height); - if (new_width > term->sixel.max_width || - new_height > term->sixel.max_height) - { - LOG_WARN("maximum image dimensions reached"); - return false; + if (unlikely(new_width > term->sixel.max_width)) { + LOG_WARN("maximum image width exceeded, truncating"); + new_width = term->sixel.max_width; + } + + if (unlikely(new_height > term->sixel.max_height)) { + LOG_WARN("maximum image height exceeded, truncating"); + new_height = term->sixel.max_height; } uint32_t *old_data = term->sixel.image.data; @@ -1291,9 +1296,9 @@ sixel_add_many(struct terminal *term, uint8_t c, unsigned count) int width = term->sixel.image.width; if (unlikely(col + count - 1 >= width)) { - width = col + count; - if (unlikely(!resize_horizontally(term, width))) - return; + resize_horizontally(term, col + count); + width = term->sixel.image.width; + count = min(count, width - col); } uint32_t color = term->sixel.color; @@ -1412,7 +1417,8 @@ decgra(struct terminal *term, uint8_t c) /* This ensures the sixel’s final image size is *at least* * this large */ - term->sixel.max_non_empty_row_no = pv - 1; + term->sixel.max_non_empty_row_no = + min(pv, term->sixel.image.height) - 1; } term->sixel.state = SIXEL_DECSIXEL;