From 834425d90b25933356fc3ad05135989162a0f356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 26 Sep 2024 14:17:02 +0300 Subject: [PATCH 21/28] 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: --- .../gst-plugins-good/gst/isomp4/qtdemux.c | 84 ++++++++++--------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c b/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c index 1e95f5b5f2..f8fbc6395c 100644 --- a/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c +++ b/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c @@ -13120,47 +13120,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.47.0