1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
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
|