Add patches for CVE-2026-2923 and CVE-2026-3082

Resolves: RHEL-156118, RHEL-156189
This commit is contained in:
Wim Taymans 2026-03-31 11:50:19 +02:00
parent bec699998a
commit c4df609397
5 changed files with 643 additions and 2 deletions

View File

@ -0,0 +1,94 @@
From e0eb8a3227b7cba80939aaeb953e5d1229f695a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Wed, 25 Feb 2026 17:22:52 +0200
Subject: [PATCH 1/4] dvbsuboverlay: Mark parsed byte array as const
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10884>
---
.../gst/dvbsuboverlay/dvb-sub.c | 21 ++++++++++---------
.../gst/dvbsuboverlay/dvb-sub.h | 2 +-
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
index c3ed520513..d49828929c 100644
--- a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
+++ b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
@@ -373,8 +373,8 @@ dvb_sub_init (void)
}
static void
-_dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
- gint buf_size)
+_dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id,
+ const guint8 * buf, gint buf_size)
{ /* FIXME: Use guint for buf_size here and in many other places? */
DVBSubRegionDisplay *display;
DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
@@ -451,8 +451,8 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
}
static void
-_dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
- gint buf_size)
+_dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id,
+ const guint8 * buf, gint buf_size)
{
const guint8 *buf_end = buf + buf_size;
guint8 region_id;
@@ -574,8 +574,8 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
}
static void
-_dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
- gint buf_size)
+_dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id,
+ const guint8 * buf, gint buf_size)
{
const guint8 *buf_end = buf + buf_size;
guint8 clut_id;
@@ -1076,8 +1076,8 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub,
}
static void
-_dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
- gint buf_size)
+_dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id,
+ const guint8 * buf, gint buf_size)
{
const guint8 *buf_end = buf + buf_size;
guint object_id;
@@ -1147,7 +1147,7 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
}
static gint
-_dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, guint8 * buf,
+_dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, const guint8 * buf,
gint buf_size)
{
int dds_version, info_byte;
@@ -1386,7 +1386,8 @@ dvb_sub_free (DvbSub * sub)
* 0 or positive if data was handled. If positive, then amount of data consumed on success. FIXME: List the positive return values.
*/
gint
-dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len)
+dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, const guint8 * data,
+ gint len)
{
unsigned int pos = 0;
guint8 segment_type;
diff --git a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.h b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.h
index c986422a6a..0f78a171b1 100644
--- a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.h
+++ b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.h
@@ -129,7 +129,7 @@ typedef struct {
DvbSub *dvb_sub_new (void);
void dvb_sub_free (DvbSub * sub);
-gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len);
+gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, const guint8 *data, gint len);
void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data);
void dvb_subtitles_free (DVBSubtitles *sub);
--
2.53.0

View File

@ -0,0 +1,442 @@
From 63fa69ec181f5defeb1193458b9322206ced4b85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Wed, 11 Feb 2026 20:45:12 +0200
Subject: [PATCH 2/4] dvbsuboverlay: Add missing bounds checks to the parser
everywhere
Fixes SA-2026-0007, ZDI-CAN-28838, CVE-2026-2923.
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4897
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10884>
---
.../gst/dvbsuboverlay/dvb-sub.c | 186 ++++++++++--------
1 file changed, 109 insertions(+), 77 deletions(-)
diff --git a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
index d49828929c..9d7704b86d 100644
--- a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
+++ b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
@@ -585,6 +585,9 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id,
GST_MEMDUMP ("DVB clut packet", buf, buf_size);
+ if (buf_size < 1)
+ return;
+
clut_id = *buf++;
buf += 1;
@@ -601,7 +604,7 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id,
dvb_sub->clut_list = clut;
}
- while (buf + 4 < buf_end) {
+ while (buf + 2 < buf_end) {
entry_id = *buf++;
depth = (*buf) & 0xe0;
@@ -614,11 +617,15 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id,
full_range = (*buf++) & 1;
if (full_range) {
+ if (buf + 4 > buf_end)
+ break;
y = *buf++;
cr = *buf++;
cb = *buf++;
alpha = *buf++;
} else {
+ if (buf + 2 > buf_end)
+ break;
y = buf[0] & 0xfc;
cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4;
cb = (buf[1] << 2) & 0xf0;
@@ -633,11 +640,11 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id,
GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, y, cb, cr,
alpha);
- if (depth & 0x80)
+ if ((depth & 0x80) && entry_id < 4)
clut->clut4[entry_id] = AYUV (y, cb, cr, 255 - alpha);
- if (depth & 0x40)
+ if ((depth & 0x40) && entry_id < 16)
clut->clut16[entry_id] = AYUV (y, cb, cr, 255 - alpha);
- if (depth & 0x20)
+ if ((depth & 0x20) && entry_id < 256)
clut->clut256[entry_id] = AYUV (y, cb, cr, 255 - alpha);
}
}
@@ -649,8 +656,6 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len,
const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table)
{
GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size);
- /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */
-
gboolean stop_parsing = FALSE;
guint32 bits = 0;
guint32 pixels_read = 0;
@@ -661,23 +666,29 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len,
while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 1)) {
guint run_length = 0, clut_index = 0;
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 2))
+ goto not_enough_data;
if (bits) { /* 2-bit_pixel-code */
run_length = 1;
clut_index = bits;
} else { /* 2-bit_zero */
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1))
+ goto not_enough_data;
if (bits == 1) { /* switch_1 == '1' */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 3);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3))
+ goto not_enough_data;
run_length += 3;
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2))
+ goto not_enough_data;
} else { /* switch_1 == '0' */
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1))
+ goto not_enough_data;
if (bits == 1) { /* switch_2 == '1' */
run_length = 1; /* 1x pseudo-colour '00' */
} else { /* switch_2 == '0' */
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 2))
+ goto not_enough_data;
switch (bits) { /* switch_3 */
case 0x0: /* end of 2-bit/pixel_code_string */
stop_parsing = TRUE;
@@ -686,14 +697,18 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len,
run_length = 2;
break;
case 0x2: /* the following 6 bits contain run length coded pixel data */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4))
+ goto not_enough_data;
run_length += 12;
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2))
+ goto not_enough_data;
break;
case 0x3: /* the following 10 bits contain run length coded pixel data */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8))
+ goto not_enough_data;
run_length += 29;
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2))
+ goto not_enough_data;
break;
}
}
@@ -727,13 +742,18 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len,
pixels_read += run_length;
}
- // FIXME: Test skip_to_byte instead of adding 7 bits, once everything else is working good
- //gst_bit_reader_skip_to_byte (&gb);
- *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3;
+ gst_bit_reader_skip_to_byte (&gb);
+ *srcbuf = gb.data + gb.byte;
GST_TRACE ("PIXEL: returning, read %u pixels", pixels_read);
// FIXME: Shouldn't need this variable if tracking things in the loop better
return pixels_read;
+
+not_enough_data:
+ GST_WARNING ("Not enough data");
+ // Go to the end of the buffer so the caller stops parsing
+ *srcbuf += buf_size;
+ return 0;
}
// FFMPEG-FIXME: The same code in ffmpeg is much more complex, it could use the same
@@ -743,7 +763,6 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len,
const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table)
{
GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size);
- /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */
gboolean stop_parsing = FALSE;
guint32 bits = 0;
guint32 pixels_read = 0;
@@ -755,28 +774,35 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len,
while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 3)) {
guint run_length = 0, clut_index = 0;
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 4))
+ goto not_enough_data;
if (bits) {
run_length = 1;
clut_index = bits;
} else {
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1))
+ goto not_enough_data;
if (bits == 0) { /* switch_1 == '0' */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 3);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3))
+ goto not_enough_data;
if (!run_length) {
stop_parsing = TRUE;
} else {
run_length += 2;
}
} else { /* switch_1 == '1' */
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1))
+ goto not_enough_data;
if (bits == 0) { /* switch_2 == '0' */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 2))
+ goto not_enough_data;
run_length += 4;
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4))
+ goto not_enough_data;
} else { /* switch_2 == '1' */
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 2))
+ goto not_enough_data;
switch (bits) {
case 0x0: /* switch_3 == '00' */
run_length = 1; /* 1 pixel of pseudo-color 0 */
@@ -785,14 +811,18 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len,
run_length = 2; /* 2 pixels of pseudo-color 0 */
break;
case 0x2: /* switch_3 == '10' */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4))
+ goto not_enough_data;
run_length += 9;
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4))
+ goto not_enough_data;
break;
case 0x3: /* switch_3 == '11' */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8))
+ goto not_enough_data;
run_length += 25;
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4))
+ goto not_enough_data;
break;
}
}
@@ -826,14 +856,19 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len,
pixels_read += run_length;
}
- // FIXME: Test skip_to_byte instead of adding 7 bits, once everything else is working good
- //gst_bit_reader_skip_to_byte (&gb);
- *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3;
+ gst_bit_reader_skip_to_byte (&gb);
+ *srcbuf = gb.data + gb.byte;
GST_LOG ("Returning with %u pixels read", pixels_read);
// FIXME: Shouldn't need this variable if tracking things in the loop better
return pixels_read;
+
+not_enough_data:
+ GST_WARNING ("Not enough data");
+ // Go to the end of the buffer so the caller stops parsing
+ *srcbuf += buf_size;
+ return 0;
}
static int
@@ -841,8 +876,6 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len,
const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table)
{
GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size);
- /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */
-
gboolean stop_parsing = FALSE;
guint32 bits = 0;
guint32 pixels_read = 0;
@@ -858,23 +891,29 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len,
/* Rephrased - it's better to work with bytes with default value '0' instead of reading from memory we don't own. */
while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 7)) {
guint run_length = 0, clut_index = 0;
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
+
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 8))
+ goto not_enough_data;
if (bits) { /* 8-bit_pixel-code */
run_length = 1;
clut_index = bits;
} else { /* 8-bit_zero */
- bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1))
+ goto not_enough_data;
if (bits == 0) { /* switch_1 == '0' */
/* run_length_1-127 for pseudo-colour _entry) '0x00' */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 7);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7))
+ goto not_enough_data;
if (run_length == 0) { /* end_of_string_signal */
stop_parsing = TRUE;
}
} else { /* switch_1 == '1' */
/* run_length_3-127 */
- run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 7);
- clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7))
+ goto not_enough_data;
+ if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 8))
+ goto not_enough_data;
if (run_length < 3) {
GST_WARNING ("runlength value was %u, but the spec requires it "
@@ -912,10 +951,17 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len,
GST_LOG ("Returning with %u pixels read", pixels_read);
- *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3;
+ gst_bit_reader_skip_to_byte (&gb);
+ *srcbuf = gb.data + gb.byte;
// FIXME: Shouldn't need this variable if tracking things in the loop better
return pixels_read;
+
+not_enough_data:
+ GST_WARNING ("Not enough data");
+ // Go to the end of the buffer so the caller stops parsing
+ *srcbuf += buf_size;
+ return 0;
}
static void
@@ -928,7 +974,6 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub,
guint8 *pbuf;
int x_pos, y_pos;
int i;
- gboolean dest_buf_filled = FALSE;
guint8 map2to4[] = { 0x0, 0x7, 0x8, 0xf };
guint8 map2to8[] = { 0x00, 0x77, 0x88, 0xff };
@@ -963,24 +1008,13 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub,
// FFMPEG-FIXME: ffmpeg doesn't check for equality and so can overflow destination buffer later on with bad input data
// FFMPEG-FIXME: However that makes it warn on end_of_object_line and map tables as well, so we add the dest_buf_filled tracking
- // FIXME: Removed x_pos checking here, because we don't want to turn dest_buf_filled to TRUE permanently in that case
- // FIXME: We assume that region->width - x_pos as dbuf_len to read_nbit_string will take care of that case nicely;
- // FIXME: That is, that read_nbit_string never scribbles anything if dbuf_len passed to it is zero due to this.
- if (y_pos >= region->height) {
- dest_buf_filled = TRUE;
+ if (x_pos >= region->width || y_pos >= region->height) {
+ GST_WARNING ("Invalid object location for data_type 0x%x!", *buf);
+ return;
}
switch (*buf++) {
case 0x10:
- if (dest_buf_filled) {
- /* FIXME: Be more verbose */
- GST_WARNING ("Invalid object location for data_type 0x%x!",
- *(buf - 1));
- GST_MEMDUMP ("Remaining data after invalid object location:", buf,
- (guint) (buf_end - buf));
- return;
- }
-
if (region->depth == 8)
map_table = map2to8;
else if (region->depth == 4)
@@ -995,15 +1029,6 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub,
region->width - x_pos, &buf, buf_end - buf, non_mod, map_table);
break;
case 0x11:
- if (dest_buf_filled) {
- /* FIXME: Be more verbose */
- GST_WARNING ("Invalid object location for data_type 0x%x!",
- *(buf - 1));
- GST_MEMDUMP ("Remaining data after invalid object location:", buf,
- buf_end - buf);
- return; // FIXME: Perhaps tell read_nbit_string that dbuf_len is zero and let it walk the bytes regardless? (Same FIXME for 2bit and 8bit)
- }
-
if (region->depth < 4) {
GST_WARNING ("4-bit pixel string in %d-bit region!", region->depth);
return;
@@ -1024,15 +1049,6 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub,
GST_DEBUG ("READ_4BIT_STRING finished: buf pointer now %p", buf);
break;
case 0x12:
- if (dest_buf_filled) {
- /* FIXME: Be more verbose */
- GST_WARNING ("Invalid object location for data_type 0x%x!",
- *(buf - 1));
- GST_MEMDUMP ("Remaining data after invalid object location:",
- buf, (guint) (buf_end - buf));
- return;
- }
-
if (region->depth < 8) {
GST_WARNING ("8-bit pixel string in %d-bit region!", region->depth);
return;
@@ -1046,19 +1062,29 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub,
case 0x20:
GST_DEBUG ("handling map2to4 table data");
- /* FIXME: I don't see any guards about buffer size here - buf++ happens with the switch, but
- * FIXME: buffer is walked without length checks? Same deal in other map table cases */
+ if (buf + 2 > buf_end) {
+ GST_WARNING ("map2to4 table too short");
+ return;
+ }
map2to4[0] = (*buf) >> 4;
map2to4[1] = (*buf++) & 0xf;
map2to4[2] = (*buf) >> 4;
map2to4[3] = (*buf++) & 0xf;
break;
case 0x21:
+ if (buf + 4 > buf_end) {
+ GST_WARNING ("map2to8 table too short");
+ return;
+ }
GST_DEBUG ("handling map2to8 table data");
for (i = 0; i < 4; i++)
map2to8[i] = *buf++;
break;
case 0x22:
+ if (buf + 16 > buf_end) {
+ GST_WARNING ("map4to8 table too short");
+ return;
+ }
GST_DEBUG ("handling map4to8 table data");
for (i = 0; i < 16; i++)
map4to8[i] = *buf++;
@@ -1085,6 +1111,9 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id,
guint8 coding_method, non_modifying_color;
+ if (buf_size < 3)
+ return;
+
object_id = GST_READ_UINT16_BE (buf);
buf += 2;
@@ -1107,6 +1136,9 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id,
DVBSubObjectDisplay *display;
guint16 top_field_len, bottom_field_len;
+ if (buf + 4 > buf_end)
+ return;
+
top_field_len = GST_READ_UINT16_BE (buf);
buf += 2;
bottom_field_len = GST_READ_UINT16_BE (buf);
--
2.53.0

View File

@ -0,0 +1,55 @@
From ff291516bd4f51610b2914ebc72a7d238233bad2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 12 Feb 2026 09:50:23 +0200
Subject: [PATCH 3/4] dvbsuboverlay: Avoid integer overflows and unreasonably
large displays/regions
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10884>
---
.../gst/dvbsuboverlay/dvb-sub.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
index 9d7704b86d..e44b8e2631 100644
--- a/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
+++ b/subprojects/gst-plugins-bad/gst/dvbsuboverlay/dvb-sub.c
@@ -483,6 +483,17 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id,
region->height = GST_READ_UINT16_BE (buf);
buf += 2;
+ /* Avoid integer overflows and also clamp to a reasonable size of 8kx8k for
+ * the region size. We allow 16kx16k display sizes. */
+ if (region->width > 8192 || region->height > 8192) {
+ GST_WARNING ("too large region of %ux%x", region->width, region->height);
+ g_free (region->pbuf);
+ region->pbuf = NULL;
+ region->buf_size = 0;
+ region->width = region->height = 0;
+ return;
+ }
+
if (region->width * region->height != region->buf_size) { /* FIXME: Read closer from spec what happens when dimensions change */
g_free (region->pbuf);
@@ -1196,6 +1207,18 @@ _dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, const guint8 * buf,
display_height = GST_READ_UINT16_BE (buf) + 1;
buf += 2;
+ /* Avoid integer overflows and also clamp to a reasonable size of 16kx16k */
+ if (display_width > 16384 || display_height > 16384) {
+ GST_WARNING ("too large display size of %ux%x", display_width,
+ display_height);
+ /* Reset to the initial values */
+ dvb_sub->display_def.version = -1;
+ dvb_sub->display_def.window_flag = 0;
+ dvb_sub->display_def.display_width = 720;
+ dvb_sub->display_def.display_height = 576;
+ return -1;
+ }
+
if ((display_width != dvb_sub->display_def.display_width)
|| (display_height != dvb_sub->display_def.display_height)) {
dvb_sub->display_def.display_width = display_width;
--
2.53.0

View File

@ -0,0 +1,42 @@
From d569264a87740fc5fac702a90d8546ce5dfb15e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?=
<vjaquez@igalia.com>
Date: Wed, 11 Feb 2026 22:07:49 +0100
Subject: [PATCH 4/4] libs: jpegparser: boundary checks before copying it
READ_BYTES macro reads data from a byte reader and then copy it to a storage
variable. This patch adds a validation that the length to read cannot be bigger
than the storage size.
This macro right now is used only for storage variables of guint8 arrays.
We have validated in the specification (sections F.1.2.1.2 and F.1.2.2.1 in ITU
T.81) that Huffman tables (both AC and DC) aren't bigger than 256.
Fixes SA-2026-0003, CVE-2026-3082, ZDI-CAN-28840.
Fixes: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4899>
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10885>
---
.../gst-plugins-bad/gst-libs/gst/codecparsers/gstjpegparser.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstjpegparser.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstjpegparser.c
index 0cb5d0b739..fd66f6cfdf 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstjpegparser.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstjpegparser.c
@@ -77,6 +77,10 @@ ensure_debug_category (void)
#define READ_BYTES(reader, buf, length) G_STMT_START { \
const guint8 *vals; \
+ if (length > sizeof (buf)) { \
+ GST_WARNING ("data size is bigger than its storage"); \
+ goto failed; \
+ } \
if (!gst_byte_reader_get_data (reader, length, &vals)) { \
GST_WARNING ("failed to read bytes, size:%d", length); \
goto failed; \
--
2.53.0

View File

@ -26,7 +26,7 @@
Name: gstreamer1-plugins-bad-free
Version: 1.26.7
Release: 1%{?dist}
Release: 2%{?dist}
Summary: GStreamer streaming media framework "bad" plugins
License: LGPLv2+ and LGPLv2
@ -40,7 +40,11 @@ Source: https://gstreamer.freedesktop.org/src/gst-plugins-bad/gst-plugin
%endif
# https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5622
Patch0: openh264-add-license-file.patch
Patch: openh264-add-license-file.patch
Patch: 0001-dvbsuboverlay-Mark-parsed-byte-array-as-const.patch
Patch: 0002-dvbsuboverlay-Add-missing-bounds-checks-to-the-parse.patch
Patch: 0003-dvbsuboverlay-Avoid-integer-overflows-and-unreasonab.patch
Patch: 0004-libs-jpegparser-boundary-checks-before-copying-it.patch
BuildRequires: meson >= 0.48.0
BuildRequires: gcc-c++
@ -868,6 +872,10 @@ EOF
%changelog
* Tue Mar 31 2026 Wim Taymans <wtaymans@redhat.com> - 1.26.7-2
- Add patches for CVE-2026-2923 and CVE-2026-3082
Resolves: RHEL-156118, RHEL-156189
* Tue Nov 04 2025 Wim Taymans <wtaymans@redhat.com> - 1.26.7-1
- Update to 1.26.7
Resolves: RHEL-126057