Merge branch 'sixel-repeat-edge-cases'

This commit is contained in:
Daniel Eklöf 2022-02-04 18:14:32 +01:00
commit a5f8ed1b78
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 30 additions and 14 deletions

View file

@ -112,7 +112,7 @@
characters (e.g. emojis). characters (e.g. emojis).
* Rendering of CSD borders when `csd.border-width > 0` and desktop * Rendering of CSD borders when `csd.border-width > 0` and desktop
scaling has been enabled. scaling has been enabled.
* Failure to launch when `exec(3):ed with an empty argv. * Failure to launch when `exec(3)`:ed with an empty argv.
* Pasting from the primary clipboard (mouse middle clicking) did not * Pasting from the primary clipboard (mouse middle clicking) did not
reset the scrollback view to the bottom. reset the scrollback view to the bottom.
* Wrong mouse binding triggered when doing two mouse selections in * Wrong mouse binding triggered when doing two mouse selections in
@ -120,6 +120,9 @@
(https://codeberg.org/dnkl/foot/issues/883). (https://codeberg.org/dnkl/foot/issues/883).
* Bash completion giving an error when completing a list of short * Bash completion giving an error when completing a list of short
options options
* Sixel: large image resizes (triggered by e.g. large repeat counts in
`DECGRI`) are now truncated instead of ignored.
* Sixel: a repeat count of 0 in `DECGRI` now emits a single sixel.
### Security ### Security

39
sixel.c
View file

@ -1104,7 +1104,7 @@ sixel_unhook(struct terminal *term)
render_refresh(term); render_refresh(term);
} }
static bool static void
resize_horizontally(struct terminal *term, int new_width) resize_horizontally(struct terminal *term, int new_width)
{ {
LOG_DBG("resizing image horizontally: %dx(%d) -> %dx(%d)", 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); new_width, term->sixel.image.height);
if (unlikely(new_width > term->sixel.max_width)) { if (unlikely(new_width > term->sixel.max_width)) {
LOG_WARN("maximum image dimensions reached"); LOG_WARN("maximum image dimensions exceeded, truncating");
return false; new_width = term->sixel.max_width;
} }
if (unlikely(term->sixel.image.width == new_width))
return;
uint32_t *old_data = term->sixel.image.data; uint32_t *old_data = term->sixel.image.data;
const int old_width = term->sixel.image.width; const int old_width = term->sixel.image.width;
const int height = term->sixel.image.height; 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.data = new_data;
term->sixel.image.width = new_width; term->sixel.image.width = new_width;
term->sixel.row_byte_ofs = term->sixel.pos.row * new_width; term->sixel.row_byte_ofs = term->sixel.pos.row * new_width;
return true;
} }
static bool static bool
@ -1197,11 +1199,14 @@ resize(struct terminal *term, int new_width, int new_height)
term->sixel.image.width, term->sixel.image.height, term->sixel.image.width, term->sixel.image.height,
new_width, new_height); new_width, new_height);
if (new_width > term->sixel.max_width || if (unlikely(new_width > term->sixel.max_width)) {
new_height > term->sixel.max_height) LOG_WARN("maximum image width exceeded, truncating");
{ new_width = term->sixel.max_width;
LOG_WARN("maximum image dimensions reached"); }
return false;
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; 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; int width = term->sixel.image.width;
if (unlikely(col + count - 1 >= width)) { if (unlikely(col + count - 1 >= width)) {
width = col + count; resize_horizontally(term, col + count);
if (unlikely(!resize_horizontally(term, width))) width = term->sixel.image.width;
return; count = min(count, width - col);
} }
uint32_t color = term->sixel.color; uint32_t color = term->sixel.color;
@ -1412,7 +1417,8 @@ decgra(struct terminal *term, uint8_t c)
/* This ensures the sixels final image size is *at least* /* This ensures the sixels final image size is *at least*
* this large */ * 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; term->sixel.state = SIXEL_DECSIXEL;
@ -1445,9 +1451,16 @@ decgri(struct terminal *term, uint8_t c)
unsigned count = term->sixel.param; unsigned count = term->sixel.param;
if (likely(count > 0)) if (likely(count > 0))
sixel_add_many(term, c - 63, count); sixel_add_many(term, c - 63, count);
else if (unlikely(count == 0))
sixel_add_many(term, c - 63, 1);
term->sixel.state = SIXEL_DECSIXEL; term->sixel.state = SIXEL_DECSIXEL;
break; break;
} }
default:
term->sixel.state = SIXEL_DECSIXEL;
sixel_put(term, c);
break;
} }
} }