From 64fa1ec0de71db28387a45819681ba760a71e6bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 26 Sep 2024 14:17:02 +0300
Subject: [PATCH 07/13] qtdemux: Make sure enough data is available before
 reading wave header node

Thanks to Antonio Morales for finding and reporting the issue.

Fixes GHSL-2024-236
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3843

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8109>

CVE: CVE-2024-47543
Upstream-Status: Backport [https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/64fa1ec0de71db28387a45819681ba760a71e6bc]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
 gst/isomp4/qtdemux.c | 84 ++++++++++++++++++++++++--------------------
 1 file changed, 45 insertions(+), 39 deletions(-)

diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index ce1a1b8d59..ed83227d70 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -13139,47 +13139,53 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
         } else {
           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
           const guint8 *data = stsd_entry_data + offset + 16;
-          GNode *wavenode;
-          GNode *waveheadernode;
-
-          wavenode = g_node_new ((guint8 *) data);
-          if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
-            const guint8 *waveheader;
-            guint32 headerlen;
-
-            waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
-            if (waveheadernode) {
-              waveheader = (const guint8 *) waveheadernode->data;
-              headerlen = QT_UINT32 (waveheader);
-
-              if (headerlen > 8) {
-                gst_riff_strf_auds *header = NULL;
-                GstBuffer *headerbuf;
-                GstBuffer *extra;
-
-                waveheader += 8;
-                headerlen -= 8;
-
-                headerbuf = gst_buffer_new_and_alloc (headerlen);
-                gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
-
-                if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
-                        headerbuf, &header, &extra)) {
-                  gst_caps_unref (entry->caps);
-                  /* FIXME: Need to do something with the channel reorder map */
-                  entry->caps =
-                      gst_riff_create_audio_caps (header->format, NULL, header,
-                      extra, NULL, NULL, NULL);
-
-                  if (extra)
-                    gst_buffer_unref (extra);
-                  g_free (header);
+
+          if (len < datalen || len - datalen < offset + 16) {
+            GST_WARNING_OBJECT (qtdemux, "Not enough data for waveheadernode");
+          } else {
+            GNode *wavenode;
+            GNode *waveheadernode;
+
+            wavenode = g_node_new ((guint8 *) data);
+            if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
+              const guint8 *waveheader;
+              guint32 headerlen;
+
+              waveheadernode =
+                  qtdemux_tree_get_child_by_type (wavenode, fourcc);
+              if (waveheadernode) {
+                waveheader = (const guint8 *) waveheadernode->data;
+                headerlen = QT_UINT32 (waveheader);
+
+                if (headerlen > 8) {
+                  gst_riff_strf_auds *header = NULL;
+                  GstBuffer *headerbuf;
+                  GstBuffer *extra;
+
+                  waveheader += 8;
+                  headerlen -= 8;
+
+                  headerbuf = gst_buffer_new_and_alloc (headerlen);
+                  gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
+
+                  if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
+                          headerbuf, &header, &extra)) {
+                    gst_caps_unref (entry->caps);
+                    /* FIXME: Need to do something with the channel reorder map */
+                    entry->caps =
+                        gst_riff_create_audio_caps (header->format, NULL,
+                        header, extra, NULL, NULL, NULL);
+
+                    if (extra)
+                      gst_buffer_unref (extra);
+                    g_free (header);
+                  }
                 }
-              }
-            } else
-              GST_DEBUG ("Didn't find waveheadernode for this codec");
+              } else
+                GST_DEBUG ("Didn't find waveheadernode for this codec");
+            }
+            g_node_destroy (wavenode);
           }
-          g_node_destroy (wavenode);
         }
       } else if (esds) {
         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
-- 
2.30.2

