Version in base suite: 1.26.2-1 Base version: gst-plugins-good1.0_1.26.2-1 Target version: gst-plugins-good1.0_1.26.2-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/g/gst-plugins-good1.0/gst-plugins-good1.0_1.26.2-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/g/gst-plugins-good1.0/gst-plugins-good1.0_1.26.2-1+deb13u1.dsc changelog | 8 patches/CVE-2026-46469_CVE-2026-46470.patch | 297 ++++++++++++++++++++++++++++ patches/CVE-2026-5056.patch | 87 ++++++++ patches/series | 2 4 files changed, 394 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp3b798r0o/gst-plugins-good1.0_1.26.2-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp3b798r0o/gst-plugins-good1.0_1.26.2-1+deb13u1.dsc: no acceptable signature found diff -Nru gst-plugins-good1.0-1.26.2/debian/changelog gst-plugins-good1.0-1.26.2/debian/changelog --- gst-plugins-good1.0-1.26.2/debian/changelog 2025-05-30 07:27:39.000000000 +0000 +++ gst-plugins-good1.0-1.26.2/debian/changelog 2026-05-29 20:42:20.000000000 +0000 @@ -1,3 +1,11 @@ +gst-plugins-good1.0 (1.26.2-1+deb13u1) trixie-security; urgency=medium + + * CVE-2026-5056 + * CVE-2026-46469 + * CVE-2026-46470 + + -- Moritz Mühlenhoff Fri, 29 May 2026 22:42:20 +0200 + gst-plugins-good1.0 (1.26.2-1) unstable; urgency=medium * d/copyright: remove reference to ostal address of the Free Software Foundation (FSF). diff -Nru gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-46469_CVE-2026-46470.patch gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-46469_CVE-2026-46470.patch --- gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-46469_CVE-2026-46470.patch 1970-01-01 00:00:00.000000000 +0000 +++ gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-46469_CVE-2026-46470.patch 2026-05-29 13:46:06.000000000 +0000 @@ -0,0 +1,297 @@ +From dbd4cb49e72836d2372de2d2043d28c7a7fce9c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Thu, 19 Mar 2026 10:25:22 +0200 +Subject: [PATCH] qtdemux: Avoid division by zero if 0 audio channels are +signalled + +From dc7ab66ab23a054eaa942071cfb548d47fe4ca2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Thu, 19 Mar 2026 11:00:50 +0200 +Subject: [PATCH] qtdemux: Fix bit pattern check for omitted audio channels map + +From 10fd1abfdb793641b4eb0454478e01fd74648d5c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Thu, 19 Mar 2026 10:34:54 +0200 +Subject: [PATCH] qtdemux: Validate chnl defined layout before using it to + index the layouts array + +From 34418818730bc04e41f512e65331b3f206cb5eb9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Thu, 19 Mar 2026 10:46:51 +0200 +Subject: [PATCH] qtdemux: Avoid out-of-bounds reads and writes of 64 item + audio channel positions array + + +--- gst-plugins-good1.0-1.26.2.orig/gst/isomp4/qtdemux.c ++++ gst-plugins-good1.0-1.26.2/gst/isomp4/qtdemux.c +@@ -12894,6 +12894,16 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + } + + n_channels = entry->n_channels; ++ if (n_channels == 0) { ++ GST_WARNING_OBJECT (qtdemux, "Unknown number of channels"); ++ goto error; ++ } ++ ++ if (n_channels >= 64) { ++ GST_WARNING_OBJECT (qtdemux, "Unsupported number of channels %d", ++ n_channels); ++ goto error; ++ } + + if (defined_layout == 0) { + for (unsigned int i = 0; i < n_channels; i++) { +@@ -13031,6 +13041,12 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + goto error; + } + ++ if (layout_channel_count >= 64) { ++ GST_WARNING_OBJECT (qtdemux, "Unsupported number of channels %d", ++ layout_channel_count); ++ goto error; ++ } ++ + n_channels = layout_channel_count; + for (unsigned int i = 0; i < layout_channel_count; i++) { + guint8 speaker_position; +@@ -13082,6 +13098,14 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + } + } + ++ if (defined_layout >= G_N_ELEMENTS (chnl_layouts) || ++ chnl_layouts[defined_layout][0] == ++ GST_AUDIO_CHANNEL_POSITION_INVALID) { ++ GST_WARNING_OBJECT (qtdemux, "Unsupported defined layout %u", ++ defined_layout); ++ goto error; ++ } ++ + const GstAudioChannelPosition *layout = chnl_layouts[defined_layout]; + + // Calculate number of channels: number of channels in the layout +@@ -13094,7 +13118,8 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + n_channels += 1; + } + for (unsigned int i = 0; i < 64; i++) { +- if ((omitted_channels_map >> i) == 1) { ++ // The i-th channel is omitted ++ if (((omitted_channels_map >> i) & 1) == 1) { + n_channels -= 1; + } + // No channels present +@@ -13103,6 +13128,9 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + } + } + ++ // Guaranteed above by construction ++ g_assert (n_channels < 64); ++ + // The omitted channel map defines which of the channels of the + // pre-defined layout are *not* included. + for (unsigned int c = 0; c < n_channels; c++) { +@@ -13158,7 +13186,8 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + + #ifndef GST_DISABLE_GST_DEBUG + { +- gchar *s = gst_audio_channel_positions_to_string (positions, n_channels); ++ gchar *s = ++ gst_audio_channel_positions_to_string (positions, MIN (n_channels, 64)); + + GST_DEBUG_OBJECT (qtdemux, "Retrieved channel positions %s", s); + +@@ -13166,35 +13195,41 @@ qtdemux_parse_chnl (GstQTDemux * qtdemux + } + #endif + +- guint64 channel_mask; +- GstAudioChannelPosition valid_positions[64]; +- +- if (!gst_audio_channel_positions_to_mask (positions, n_channels, FALSE, +- &channel_mask)) { +- GST_WARNING_OBJECT (qtdemux, "Can't convert channel positions to mask"); +- goto error; +- } +- +- memcpy (valid_positions, positions, sizeof (positions[0]) * n_channels); +- if (!gst_audio_channel_positions_to_valid_order (valid_positions, n_channels)) { +- GST_WARNING_OBJECT (qtdemux, +- "Can't convert channel positions to GStreamer channel order"); +- goto error; +- } ++ if (n_channels < 64) { ++ guint64 channel_mask; ++ GstAudioChannelPosition valid_positions[64]; ++ ++ if (!gst_audio_channel_positions_to_mask (positions, n_channels, FALSE, ++ &channel_mask)) { ++ GST_WARNING_OBJECT (qtdemux, "Can't convert channel positions to mask"); ++ goto error; ++ } + +- if (n_channels > 1) { +- if (!gst_audio_get_channel_reorder_map (n_channels, positions, +- valid_positions, entry->reorder_map)) { +- GST_WARNING_OBJECT (qtdemux, "Can't calculate channel reorder map"); ++ memcpy (valid_positions, positions, sizeof (positions[0]) * n_channels); ++ if (!gst_audio_channel_positions_to_valid_order (valid_positions, ++ n_channels)) { ++ GST_WARNING_OBJECT (qtdemux, ++ "Can't convert channel positions to GStreamer channel order"); + goto error; + } +- entry->needs_reorder = +- memcmp (positions, valid_positions, +- sizeof (positions[0]) * n_channels) != 0; +- } + +- gst_caps_set_simple (entry->caps, "channel-mask", GST_TYPE_BITMASK, +- channel_mask, NULL); ++ if (n_channels > 1) { ++ if (!gst_audio_get_channel_reorder_map (n_channels, positions, ++ valid_positions, entry->reorder_map)) { ++ GST_WARNING_OBJECT (qtdemux, "Can't calculate channel reorder map"); ++ goto error; ++ } ++ entry->needs_reorder = ++ memcmp (positions, valid_positions, ++ sizeof (positions[0]) * n_channels) != 0; ++ } ++ ++ gst_caps_set_simple (entry->caps, "channel-mask", GST_TYPE_BITMASK, ++ channel_mask, NULL); ++ } else { ++ gst_caps_set_simple (entry->caps, "channel-mask", GST_TYPE_BITMASK, ++ G_GUINT64_CONSTANT (0), NULL); ++ } + + // Update based on the actual channel count from this box + entry->samples_per_frame = n_channels; +@@ -14471,14 +14506,15 @@ qtdemux_parse_chan (GstQTDemux * qtdemux + } + } else if (layout_tag == AUDIO_CHANNEL_LAYOUT_TAG_DISCRETEINORDER) { + // Unordered +- n_channels = entry->n_channels; +- for (gsize i = 0; i < n_channels; i++) { ++ for (gsize i = 0; i < G_N_ELEMENTS (positions); i++) { + positions[i] = GST_AUDIO_CHANNEL_POSITION_NONE; + } + } else if (layout_tag & 0xffff) { + for (gsize i = 0; i < G_N_ELEMENTS (chan_layout_map); i++) { + if (chan_layout_map[i].tag == layout_tag) { + n_channels = layout_tag & 0xffff; ++ // Guaranteed by construction of the layout map table ++ g_assert (n_channels < 64); + memcpy (positions, chan_layout_map[i].positions, + n_channels * sizeof (GstAudioChannelPosition)); + break; +@@ -14494,7 +14530,8 @@ qtdemux_parse_chan (GstQTDemux * qtdemux + + #ifndef GST_DISABLE_GST_DEBUG + { +- gchar *s = gst_audio_channel_positions_to_string (positions, n_channels); ++ gchar *s = ++ gst_audio_channel_positions_to_string (positions, MIN (n_channels, 64)); + + GST_DEBUG_OBJECT (qtdemux, "Retrieved channel positions %s", s); + +@@ -14502,35 +14539,41 @@ qtdemux_parse_chan (GstQTDemux * qtdemux + } + #endif + +- guint64 channel_mask; +- GstAudioChannelPosition valid_positions[64]; +- +- if (!gst_audio_channel_positions_to_mask (positions, n_channels, FALSE, +- &channel_mask)) { +- GST_WARNING_OBJECT (qtdemux, "Can't convert channel positions to mask"); +- goto error; +- } +- +- memcpy (valid_positions, positions, sizeof (positions[0]) * n_channels); +- if (!gst_audio_channel_positions_to_valid_order (valid_positions, n_channels)) { +- GST_WARNING_OBJECT (qtdemux, +- "Can't convert channel positions to GStreamer channel order"); +- goto error; +- } ++ if (n_channels < 64) { ++ guint64 channel_mask; ++ GstAudioChannelPosition valid_positions[64]; ++ ++ if (!gst_audio_channel_positions_to_mask (positions, n_channels, FALSE, ++ &channel_mask)) { ++ GST_WARNING_OBJECT (qtdemux, "Can't convert channel positions to mask"); ++ goto error; ++ } + +- if (n_channels > 1) { +- if (!gst_audio_get_channel_reorder_map (n_channels, positions, +- valid_positions, entry->reorder_map)) { +- GST_WARNING_OBJECT (qtdemux, "Can't calculate channel reorder map"); ++ memcpy (valid_positions, positions, sizeof (positions[0]) * n_channels); ++ if (!gst_audio_channel_positions_to_valid_order (valid_positions, ++ n_channels)) { ++ GST_WARNING_OBJECT (qtdemux, ++ "Can't convert channel positions to GStreamer channel order"); + goto error; + } +- entry->needs_reorder = +- memcmp (positions, valid_positions, +- sizeof (positions[0]) * n_channels) != 0; +- } + +- gst_caps_set_simple (entry->caps, "channel-mask", GST_TYPE_BITMASK, +- channel_mask, NULL); ++ if (n_channels > 1) { ++ if (!gst_audio_get_channel_reorder_map (n_channels, positions, ++ valid_positions, entry->reorder_map)) { ++ GST_WARNING_OBJECT (qtdemux, "Can't calculate channel reorder map"); ++ goto error; ++ } ++ entry->needs_reorder = ++ memcmp (positions, valid_positions, ++ sizeof (positions[0]) * n_channels) != 0; ++ } ++ ++ gst_caps_set_simple (entry->caps, "channel-mask", GST_TYPE_BITMASK, ++ channel_mask, NULL); ++ } else { ++ gst_caps_set_simple (entry->caps, "channel-mask", GST_TYPE_BITMASK, ++ G_GUINT64_CONSTANT (0), NULL); ++ } + + // Update based on the actual channel count from this box + entry->samples_per_frame = n_channels; +@@ -16072,20 +16115,20 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + /* Sometimes these are set to 0 in the sound sample descriptions so + * let's try to infer useful values from the other information we + * have available */ +- if (entry->bytes_per_sample == 0) ++ if (entry->bytes_per_sample == 0 && entry->n_channels > 0) + entry->bytes_per_sample = + entry->bytes_per_frame / entry->n_channels; + if (entry->bytes_per_sample == 0) + entry->bytes_per_sample = samplesize / 8; + +- if (entry->bytes_per_frame == 0) ++ if (entry->bytes_per_frame == 0 && entry->n_channels > 0) + entry->bytes_per_frame = + entry->bytes_per_sample * entry->n_channels; + + if (entry->bytes_per_packet == 0) + entry->bytes_per_packet = entry->bytes_per_sample; + +- if (entry->samples_per_frame == 0) ++ if (entry->samples_per_frame == 0 && entry->n_channels > 0) + entry->samples_per_frame = entry->n_channels; + + if (entry->samples_per_packet == 0) +@@ -19237,7 +19280,8 @@ qtdemux_audio_caps (GstQTDemux * qtdemux + data = stsd_entry->data; + len = QT_UINT32 (data); + +- if (stsd_version == 0 && version == 0x00020000 && len >= 16 + 56) { ++ if (stsd_version == 0 && version == 0x00020000 && len >= 16 + 56 ++ && entry->n_channels > 0) { + /* sample description entry (16) + sound sample description v0 (20) */ + depth = QT_UINT32 (data + 36 + 20); + flags = QT_UINT32 (data + 36 + 24); diff -Nru gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-5056.patch gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-5056.patch --- gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-5056.patch 1970-01-01 00:00:00.000000000 +0000 +++ gst-plugins-good1.0-1.26.2/debian/patches/CVE-2026-5056.patch 2026-05-29 13:44:13.000000000 +0000 @@ -0,0 +1,87 @@ +From bad6721ca4901123e5cb57eec9d8e84d69c08597 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Fri, 13 Mar 2026 11:56:45 +0200 +Subject: [PATCH] qtdemux: Add various integer overflow and bounds checks to + uncompressed video handling + +--- gst-plugins-good1.0-1.26.2.orig/gst/isomp4/qtdemux.c ++++ gst-plugins-good1.0-1.26.2/gst/isomp4/qtdemux.c +@@ -12121,6 +12121,14 @@ qtdemux_parse_cmpd (GstQTDemux * qtdemux + + cmpd->component_count = gst_byte_reader_get_uint32_be_unchecked (reader); + ++ /* Let's use 16 as a upper bound here for now to avoid overflows and ++ * allocating lots of memory */ ++ if (cmpd->component_count > 16) { ++ GST_ERROR_OBJECT (qtdemux, "Unsupported number of cmpd components %u", ++ cmpd->component_count); ++ goto error; ++ } ++ + guint32 minimum_size = cmpd->component_count * 2 + 4; // assuming type_uris are not used + if (gst_byte_reader_get_size (reader) < minimum_size) { + GST_ERROR_OBJECT (qtdemux, "cmpd size is too short"); +@@ -12179,6 +12187,14 @@ qtdemux_parse_uncC (GstQTDemux * qtdemux + goto error; + } + ++ /* Let's use 16 as a upper bound here for now to avoid overflows and ++ * allocating lots of memory */ ++ if (uncC->component_count > 16) { ++ GST_ERROR_OBJECT (qtdemux, "Unsupported number of uncC components %u", ++ uncC->component_count); ++ goto error; ++ } ++ + guint32 expected_size = uncC->component_count * 5 + 36; + if (gst_byte_reader_get_size (reader) != expected_size) { + GST_ERROR_OBJECT (qtdemux, "uncC size is incorrect"); +@@ -12432,7 +12448,6 @@ qtdemux_get_format_from_uncv (GstQTDemux + guint32 num_components = uncC->component_count; + guint16 component_types[4]; + +- + if (uncC->version == 1) { + // Determine format with profile + // The only permitted profiles for version 1 are `rgb3`, `rgba`, and `abgr` +@@ -12460,6 +12475,11 @@ qtdemux_get_format_from_uncv (GstQTDemux + goto unsupported_feature; + } + ++ if (num_components > 4 || num_components == 0) { ++ GST_WARNING_OBJECT (qtdemux, ++ "Unsupported number of components for uncC: %u", num_components); ++ goto unsupported_feature; ++ } + + /* Assert that components are similar */ + UncompressedFrameConfigComponent *first_comp = &uncC->components[0]; +@@ -12501,6 +12521,11 @@ qtdemux_get_format_from_uncv (GstQTDemux + // Get Component Types + for (guint32 i = 0; i < num_components; i++) { + guint16 component_index = uncC->components[i].index; ++ if (component_index >= cmpd->component_count) { ++ GST_WARNING_OBJECT (qtdemux, ++ "Invalid component index %u for component %u", component_index, i); ++ goto unsupported_feature; ++ } + component_types[i] = cmpd->types[component_index]; + } + +@@ -18894,10 +18919,12 @@ qtdemux_video_caps (GstQTDemux * qtdemux + } + + format = qtdemux_get_format_from_uncv (qtdemux, &uncC, &cmpd); +- gst_video_info_set_format (&stream->pre_info, format, entry->width, +- entry->height); +- qtdemux_set_info_from_uncv (qtdemux, entry, &uncC, &stream->pre_info); +- stream->alignment = 32; ++ if (format != GST_VIDEO_FORMAT_UNKNOWN) { ++ gst_video_info_set_format (&stream->pre_info, format, entry->width, ++ entry->height); ++ qtdemux_set_info_from_uncv (qtdemux, entry, &uncC, &stream->pre_info); ++ stream->alignment = 32; ++ } + + /* Free Memory */ + qtdemux_clear_uncC (&uncC); diff -Nru gst-plugins-good1.0-1.26.2/debian/patches/series gst-plugins-good1.0-1.26.2/debian/patches/series --- gst-plugins-good1.0-1.26.2/debian/patches/series 2025-05-30 07:27:39.000000000 +0000 +++ gst-plugins-good1.0-1.26.2/debian/patches/series 2026-05-29 13:45:22.000000000 +0000 @@ -1 +1,3 @@ 0000_remove-flv-test.patch +CVE-2026-5056.patch +CVE-2026-46469_CVE-2026-46470.patch