Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
libsixel (1.10.5-1deepin3) unstable; urgency=medium

* Backport CVE-2026 security fixes from upstream saitoha/libsixel
- CVE-2026-33023: Integer overflow in DCS parameter scaling
- CVE-2026-33020: Parser cursor overflow in SIXEL decoder
- CVE-2026-33018: Null pointer dereference in palette allocation
- CVE-2026-33021: Integer overflow in highcolor encoder
- CVE-2026-44636: Integer overflows in encoder and quantizer
- CVE-2026-44637: Bad-free in libpng and improper frame lifecycle

-- lichenggang <lichenggang@uniontech.com> Thu, 21 May 2026 21:50:00 +0800

libsixel (1.10.5-1deepin2) unstable; urgency=medium

* Fix CVE-2025-9300: heap buffer overflow in encoder.c
Expand Down
24 changes: 24 additions & 0 deletions debian/patches/CVE-2026-33018.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--- a/src/fromsixel.c
+++ b/src/fromsixel.c
@@ -1030,7 +1030,7 @@ sixel_decode_raw(
alloc_size = SIXEL_PALETTE_MAX;
}
*palette = (unsigned char *)sixel_allocator_malloc(allocator, (size_t)(alloc_size * 3));
- if (palette == NULL) {
+ if (*palette == NULL) {
sixel_allocator_free(allocator, image.data);
sixel_helper_set_additional_message(
"sixel_deocde_raw: sixel_allocator_malloc() failed.");
@@ -1102,10 +1102,10 @@ sixel_decode(unsigned char /* in */ *p, /* sixel bytes */

*ncolors = image.ncolors + 1;
*palette = (unsigned char *)sixel_allocator_malloc(allocator, (size_t)(*ncolors * 3));
- if (palette == NULL) {
+ if (*palette == NULL) {
sixel_allocator_free(allocator, image.data);
sixel_helper_set_additional_message(
- "sixel_deocde_raw: sixel_allocator_malloc() failed.");
+ "sixel_decode: sixel_allocator_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
87 changes: 87 additions & 0 deletions debian/patches/CVE-2026-33020.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
--- a/src/fromsixel.c
+++ b/src/fromsixel.c
@@ -412,6 +412,50 @@ end:
}


+static SIXELSTATUS
+reject_invalid_position(parser_context_t const *context)
+{
+ SIXELSTATUS status = SIXEL_FALSE;
+
+ if (context->pos_x < 0
+ || context->pos_x >= SIXEL_WIDTH_LIMIT
+ || context->pos_y < 0
+ || context->pos_y >= SIXEL_HEIGHT_LIMIT) {
+ status = SIXEL_BAD_INPUT;
+ sixel_helper_set_additional_message(
+ "reject_invalid_position: cursor position limit exceeded.");
+ goto end;
+ }
+
+ status = SIXEL_OK;
+
+end:
+ return status;
+}
+
+
+static SIXELSTATUS
+sixel_parser_advance_line(parser_context_t *context)
+{
+ SIXELSTATUS status = SIXEL_FALSE;
+
+ if (context->pos_y < 0
+ || context->pos_y > SIXEL_HEIGHT_LIMIT - 6) {
+ status = SIXEL_BAD_INPUT;
+ sixel_helper_set_additional_message(
+ "sixel_parser_advance_line: vertical position limit exceeded.");
+ goto end;
+ }
+
+ context->pos_x = 0;
+ context->pos_y += 6;
+ status = SIXEL_OK;
+
+end:
+ return status;
+}
+
+
/* convert sixel data into indexed pixel bytes and palette data */
SIXELAPI SIXELSTATUS
sixel_decode_raw_impl(
@@ -616,13 +660,20 @@ sixel_decode_raw_impl(
break;
case '-':
/* DECGNL Graphics Next Line */
- context->pos_x = 0;
- context->pos_y += 6;
+ status = sixel_parser_advance_line(context);
+ if (SIXEL_FAILED(status)) {
+ goto end;
+ }
p++;
break;
default:
if (*p >= '?' && *p <= '~') { /* sixel characters */

+ status = reject_invalid_position(context);
+ if (SIXEL_FAILED(status)) {
+ goto end;
+ }
+
sx = image->width;
while (sx < context->pos_x + context->repeat_count) {
sx *= 2;
@@ -644,10 +695,6 @@ sixel_decode_raw_impl(
image->ncolors = context->color_index;
}

- if (context->pos_x < 0 || context->pos_y < 0) {
- status = SIXEL_BAD_INPUT;
- goto end;
- }
bits = *p - '?';

if (bits == 0) {
79 changes: 79 additions & 0 deletions debian/patches/CVE-2026-33021.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
--- a/src/tosixel.c
+++ b/src/tosixel.c
@@ -1425,10 +1425,11 @@ sixel_encode_highcolor(
unsigned char palstate[SIXEL_PALETTE_MAX];
int output_count;
int const maxcolors = 1 << 15;
- int whole_size = width * height /* for paletted_pixels */
- + maxcolors /* for rgbhit */
- + maxcolors /* for rgb2pal */
- + width * 6; /* for marks */
+ size_t image_size;
+ size_t marks_size;
+ size_t normalized_size;
+ size_t whole_size;
+ size_t maxcolors_size;
int x, y;
unsigned char *dst;
unsigned char *mptr;
@@ -1440,10 +1441,49 @@ sixel_encode_highcolor(
int orig_height;
unsigned char *pal;

+ maxcolors_size = (size_t)maxcolors;
+ if ((size_t)height > ((size_t)-1) / (size_t)width) {
+ sixel_helper_set_additional_message(
+ "sixel_encode_highcolor: image size overflow.");
+ status = SIXEL_BAD_INPUT;
+ goto error;
+ }
+ image_size = (size_t)width * (size_t)height;
+
+ if (image_size > ((size_t)-1) / 3UL) {
+ sixel_helper_set_additional_message(
+ "sixel_encode_highcolor: normalized size overflow.");
+ status = SIXEL_BAD_INPUT;
+ goto error;
+ }
+ normalized_size = image_size * 3UL;
+
+ if ((size_t)width > ((size_t)-1) / 6UL) {
+ sixel_helper_set_additional_message(
+ "sixel_encode_highcolor: marks size overflow.");
+ status = SIXEL_BAD_INPUT;
+ goto error;
+ }
+ marks_size = (size_t)width * 6UL;
+
+ if (image_size > (size_t)-1 - maxcolors_size ||
+ image_size + maxcolors_size > (size_t)-1 - maxcolors_size ||
+ image_size + maxcolors_size + maxcolors_size
+ > (size_t)-1 - marks_size) {
+ sixel_helper_set_additional_message(
+ "sixel_encode_highcolor: whole size overflow.");
+ status = SIXEL_BAD_INPUT;
+ goto error;
+ }
+ whole_size = image_size /* for paletted_pixels */
+ + maxcolors_size /* for rgbhit */
+ + maxcolors_size /* for rgb2pal */
+ + marks_size; /* for marks */
+
if (dither->pixelformat != SIXEL_PIXELFORMAT_RGB888) {
/* normalize pixelfromat */
- normalized_pixels = (unsigned char *)sixel_allocator_malloc(dither->allocator,
- (size_t)(width * height * 3));
+ normalized_pixels = (unsigned char *)sixel_allocator_malloc(
+ dither->allocator, normalized_size);
if (normalized_pixels == NULL) {
goto error;
}
@@ -1458,7 +1498,7 @@ sixel_encode_highcolor(
pixels = normalized_pixels;
}
paletted_pixels = (sixel_index_t *)sixel_allocator_malloc(dither->allocator,
- (size_t)whole_size);
+ whole_size);
if (paletted_pixels == NULL) {
goto error;
}
63 changes: 63 additions & 0 deletions debian/patches/CVE-2026-33023.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
--- a/src/fromsixel.c
+++ b/src/fromsixel.c
@@ -392,6 +392,26 @@ safe_addition_for_params(parser_context_t *context, unsigned char *p)
}


+static SIXELSTATUS
+safe_multiply_by_params_div10(int lhs, int rhs, int *result)
+{
+ SIXELSTATUS status = SIXEL_FALSE;
+
+ if (lhs > 0 && rhs > INT_MAX / lhs) {
+ status = SIXEL_BAD_INTEGER_OVERFLOW;
+ sixel_helper_set_additional_message(
+ "safe_multiply_by_params_div10: integer overflow detected.");
+ goto end;
+ }
+
+ *result = lhs * rhs / 10;
+ status = SIXEL_OK;
+
+end:
+ return status;
+}
+
+
/* convert sixel data into indexed pixel bytes and palette data */
SIXELAPI SIXELSTATUS
sixel_decode_raw_impl(
@@ -524,11 +544,31 @@ sixel_decode_raw_impl(

if (context->nparams > 2) {
/* Pn3 */
+ int scaled_pan;
+ int scaled_pad;
+
if (context->params[2] == 0) {
context->params[2] = 10;
}
- context->attributed_pan = context->attributed_pan * context->params[2] / 10;
- context->attributed_pad = context->attributed_pad * context->params[2] / 10;
+
+ status = safe_multiply_by_params_div10(
+ context->attributed_pan,
+ context->params[2],
+ &scaled_pan);
+ if (SIXEL_FAILED(status)) {
+ goto end;
+ }
+
+ status = safe_multiply_by_params_div10(
+ context->attributed_pad,
+ context->params[2],
+ &scaled_pad);
+ if (SIXEL_FAILED(status)) {
+ goto end;
+ }
+
+ context->attributed_pan = scaled_pan;
+ context->attributed_pad = scaled_pad;
if (context->attributed_pan <= 0) {
context->attributed_pan = 1;
}
Loading
Loading