sixel: force a height of at least one sixel when explicitly resizing

Applications often prefix the sixel with a raster attributes (RA)
sequence, where they tell us how large the sixel is. Strictly
speaking, this just tells us the size of the area to clear, but we use
it as a hint and pre-allocates the image buffer.

It's important to stress that it is valid to emit a MxN RA, and then
write sixel data outside of that area.

Foot handles this, in _most_ cases. We didn't handle the corner case
Mx0. I.e. a width > 0, but height == 0. No image buffer was allocated,
and we also failed to detect a resize was necessary when the
application started printing sixel data.

Much of this is for performance reason; we only check the minimum
necessary. For example, we only check if going outside the
pre-allocated *column* while printing sixels. *Rows* are checked on a
graphical newline.

In other words, the *current* row has to be valid when writing
sixels. And in case of Mx0, it wasn't.

Fix by forcing a height of at least one sixel (typically 6 pixels).

Closes #2267
This commit is contained in:
Daniel Eklöf 2026-01-28 09:21:57 +01:00
parent 3a2eb80d83
commit 6fbb9b7d3b
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 6 additions and 0 deletions

View file

@ -124,9 +124,12 @@
* Regression: visual glitches in rare circumstances.
* Key release events for shortcuts being sent to the client
application (kitty keyboard protocol only) ([#2257][2257]).
* Crash when application emits sixel RA with a height of 0, a width >
0, and then starts writing sixel data ([#2267][2267]).
[2232]: https://codeberg.org/dnkl/foot/issues/2232
[2257]: https://codeberg.org/dnkl/foot/issues/2257
[2267]: https://codeberg.org/dnkl/foot/issues/2267
### Security

View file

@ -1559,6 +1559,9 @@ resize(struct terminal *term, int new_width_mutable, int new_height_mutable)
new_height_mutable = term->sixel.max_height;
}
if (unlikely(new_height_mutable == 0)) {
new_height_mutable = 6 * term->sixel.pan;
}
uint32_t *old_data = term->sixel.image.data;
const int old_width = term->sixel.image.width;