https://bugs.gentoo.org/974286
https://gstreamer.freedesktop.org/security/sa-2026-0016.html
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11252

From bad6721ca4901123e5cb57eec9d8e84d69c08597 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Fri, 13 Mar 2026 11:56:45 +0200
Subject: [PATCH] qtdemux: Add various integer overflow and bounds checks to
 uncompressed video handling

Fixes ZDI-CAN-29392
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4963

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11252>
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -12319,6 +12319,14 @@ qtdemux_parse_cmpd (GstQTDemux * qtdemux, GstByteReader * reader,
 
   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");
@@ -12377,6 +12385,14 @@ qtdemux_parse_uncC (GstQTDemux * qtdemux, GstByteReader * reader,
     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");
@@ -12630,7 +12646,6 @@ qtdemux_get_format_from_uncv (GstQTDemux * qtdemux,
   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`
@@ -12658,6 +12673,11 @@ qtdemux_get_format_from_uncv (GstQTDemux * qtdemux,
     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];
@@ -12699,6 +12719,11 @@ qtdemux_get_format_from_uncv (GstQTDemux * qtdemux,
   // 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];
   }
 
@@ -19311,10 +19336,12 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       }
 
       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);
-- 
GitLab

