From 13b48016b3ef1e822c393c2871b0a561ce19ecb3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Fri, 4 Oct 2024 13:00:57 +0300
Subject: [PATCH 1/7] wavparse: Check for short reads when parsing headers in
 pull mode

And also return the actual flow return to the caller instead of always returning
GST_FLOW_ERROR.

Thanks to Antonio Morales for finding and reporting the issue.

Fixes GHSL-2024-258, GHSL-2024-260
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3886
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3888

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

CVE: CVE-2024-47775
CVE: CVE-2024-47776
CVE: CVE-2024-47777
CVE: CVE-2024-47778
Upstream-Status: Backport [https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/13b48016b3ef1e822c393c2871b0a561ce19ecb3]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
 gst/wavparse/gstwavparse.c | 63 ++++++++++++++++++++++++++++----------
 1 file changed, 46 insertions(+), 17 deletions(-)

diff --git a/gst/wavparse/gstwavparse.c b/gst/wavparse/gstwavparse.c
index d074f273c5..97d5591fae 100644
--- a/gst/wavparse/gstwavparse.c
+++ b/gst/wavparse/gstwavparse.c
@@ -1096,6 +1096,24 @@ parse_ds64 (GstWavParse * wav, GstBuffer * buf)
   return TRUE;
 }
 
+static GstFlowReturn
+gst_wavparse_pull_range_exact (GstWavParse * wav, guint64 offset, guint size,
+    GstBuffer ** buffer)
+{
+  GstFlowReturn res;
+
+  res = gst_pad_pull_range (wav->sinkpad, offset, size, buffer);
+  if (res != GST_FLOW_OK)
+    return res;
+
+  if (gst_buffer_get_size (*buffer) < size) {
+    gst_clear_buffer (buffer);
+    return GST_FLOW_EOS;
+  }
+
+  return res;
+}
+
 static GstFlowReturn
 gst_wavparse_stream_headers (GstWavParse * wav)
 {
@@ -1291,9 +1309,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
 
       buf = NULL;
       if ((res =
-              gst_pad_pull_range (wav->sinkpad, wav->offset, 8,
+              gst_wavparse_pull_range_exact (wav, wav->offset, 8,
                   &buf)) != GST_FLOW_OK)
-        goto header_read_error;
+        goto header_pull_error;
       gst_buffer_map (buf, &map, GST_MAP_READ);
       tag = GST_READ_UINT32_LE (map.data);
       size = GST_READ_UINT32_LE (map.data + 4);
@@ -1396,9 +1414,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
             gst_buffer_unref (buf);
             buf = NULL;
             if ((res =
-                    gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
+                    gst_wavparse_pull_range_exact (wav, wav->offset + 8,
                         data_size, &buf)) != GST_FLOW_OK)
-              goto header_read_error;
+              goto header_pull_error;
             gst_buffer_extract (buf, 0, &wav->fact, 4);
             wav->fact = GUINT32_FROM_LE (wav->fact);
             gst_buffer_unref (buf);
@@ -1443,9 +1461,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
           gst_buffer_unref (buf);
           buf = NULL;
           if ((res =
-                  gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
-                      size, &buf)) != GST_FLOW_OK)
-            goto header_read_error;
+                  gst_wavparse_pull_range_exact (wav, wav->offset + 8, size,
+                      &buf)) != GST_FLOW_OK)
+            goto header_pull_error;
           gst_buffer_map (buf, &map, GST_MAP_READ);
           acid = (const gst_riff_acid *) map.data;
           tempo = acid->tempo;
@@ -1483,9 +1501,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
           gst_buffer_unref (buf);
           buf = NULL;
           if ((res =
-                  gst_pad_pull_range (wav->sinkpad, wav->offset, 12,
+                  gst_wavparse_pull_range_exact (wav, wav->offset, 12,
                       &buf)) != GST_FLOW_OK)
-            goto header_read_error;
+            goto header_pull_error;
           gst_buffer_extract (buf, 8, &ltag, 4);
           ltag = GUINT32_FROM_LE (ltag);
         }
@@ -1512,9 +1530,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
               buf = NULL;
               if (data_size > 0) {
                 if ((res =
-                        gst_pad_pull_range (wav->sinkpad, wav->offset,
+                        gst_wavparse_pull_range_exact (wav, wav->offset,
                             data_size, &buf)) != GST_FLOW_OK)
-                  goto header_read_error;
+                  goto header_pull_error;
               }
             }
             if (data_size > 0) {
@@ -1552,9 +1570,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
               buf = NULL;
               wav->offset += 12;
               if ((res =
-                      gst_pad_pull_range (wav->sinkpad, wav->offset,
+                      gst_wavparse_pull_range_exact (wav, wav->offset,
                           data_size, &buf)) != GST_FLOW_OK)
-                goto header_read_error;
+                goto header_pull_error;
               gst_buffer_map (buf, &map, GST_MAP_READ);
               gst_wavparse_adtl_chunk (wav, (const guint8 *) map.data,
                   data_size);
@@ -1598,9 +1616,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
           gst_buffer_unref (buf);
           buf = NULL;
           if ((res =
-                  gst_pad_pull_range (wav->sinkpad, wav->offset,
+                  gst_wavparse_pull_range_exact (wav, wav->offset,
                       data_size, &buf)) != GST_FLOW_OK)
-            goto header_read_error;
+            goto header_pull_error;
           gst_buffer_map (buf, &map, GST_MAP_READ);
           if (!gst_wavparse_cue_chunk (wav, (const guint8 *) map.data,
                   data_size)) {
@@ -1642,9 +1660,9 @@ gst_wavparse_stream_headers (GstWavParse * wav)
           gst_buffer_unref (buf);
           buf = NULL;
           if ((res =
-                  gst_pad_pull_range (wav->sinkpad, wav->offset,
+                  gst_wavparse_pull_range_exact (wav, wav->offset,
                       data_size, &buf)) != GST_FLOW_OK)
-            goto header_read_error;
+            goto header_pull_error;
           gst_buffer_map (buf, &map, GST_MAP_READ);
           if (!gst_wavparse_smpl_chunk (wav, (const guint8 *) map.data,
                   data_size)) {
@@ -1796,6 +1814,17 @@ header_read_error:
         ("Couldn't read in header %d (%s)", res, gst_flow_get_name (res)));
     goto fail;
   }
+header_pull_error:
+  {
+    if (res == GST_FLOW_EOS) {
+      GST_WARNING_OBJECT (wav, "Couldn't pull header %d (%s)", res,
+          gst_flow_get_name (res));
+    } else {
+      GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
+          ("Couldn't pull header %d (%s)", res, gst_flow_get_name (res)));
+    }
+    goto exit;
+  }
 }
 
 /*
-- 
2.30.2

