From fa17e30ba717e914f2559d48a5638b83457dd534 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Fri, 20 Dec 2024 11:21:26 +0800 Subject: [PATCH] Fix CVE-2024-47544 and CVE-2024-47545 --- CVE-2024-47544.patch | 49 ++++ CVE-2024-47545-pre1.patch | 243 +++++++++++++++++++ CVE-2024-47545-pre2.patch | 116 +++++++++ CVE-2024-47545.patch | 444 +++++++++++++++++++++++++++++++++++ gstreamer1-plugins-good.spec | 9 +- 5 files changed, 860 insertions(+), 1 deletion(-) create mode 100644 CVE-2024-47544.patch create mode 100644 CVE-2024-47545-pre1.patch create mode 100644 CVE-2024-47545-pre2.patch create mode 100644 CVE-2024-47545.patch diff --git a/CVE-2024-47544.patch b/CVE-2024-47544.patch new file mode 100644 index 0000000..a644a16 --- /dev/null +++ b/CVE-2024-47544.patch @@ -0,0 +1,49 @@ +Backport of: + +From 8e884e4e31649a9fc19095d6501a1143b074aba8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Fri, 27 Sep 2024 09:47:50 +0300 +Subject: [PATCH] qtdemux: Fix error handling when parsing cenc sample groups + fails + +Thanks to Antonio Morales for finding and reporting the issue. + +Fixes GHSL-2024-238, GHSL-2024-239, GHSL-2024-240 +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3846 + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 25 ++++++++++++++----- + 1 file changed, 19 insertions(+), 6 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -11090,12 +11090,15 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + if (stream->subtype != FOURCC_soun) { + GST_ERROR_OBJECT (qtdemux, + "Unexpeced stsd type 'aavd' outside 'soun' track"); ++ goto corrupt_file; + } else { + /* encrypted audio with sound sample description v0 */ + GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc); + stream->protected = TRUE; +- if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc)) ++ if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc)) { + GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info"); ++ goto corrupt_file; ++ } + } + } + +@@ -11104,8 +11107,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + * with the same type */ + GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc); + stream->protected = TRUE; +- if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc)) ++ if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc)) { + GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info"); ++ goto corrupt_file; ++ } + } + + if (stream->subtype == FOURCC_vide) { diff --git a/CVE-2024-47545-pre1.patch b/CVE-2024-47545-pre1.patch new file mode 100644 index 0000000..7f6a49f --- /dev/null +++ b/CVE-2024-47545-pre1.patch @@ -0,0 +1,243 @@ +From fd96fc23c53dcd95becfcca06d471e92923265ab Mon Sep 17 00:00:00 2001 +From: Justin Chadwell +Date: Wed, 2 Sep 2020 10:49:40 +0100 +Subject: [PATCH] qtdemux: use unsigned int types to store result of QT_UINT32 + +In a few cases throughout qtdemux, the results of QT_UINT32 were being +stored in a signed integer, which could cause subtle bugs in the case of +an integer overflow, even allowing the the result to equal a negative +number! + +This patch prevents this by simply storing the results of this function +call properly in an unsigned integer type. Additionally, we fix up the +length checking with stsd parsing to prevent cases of child atoms +exceeding their parent atom sizes. + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 76 ++++++++++++------- + 1 file changed, 47 insertions(+), 29 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -10074,8 +10074,8 @@ qtdemux_parse_segments (GstQTDemux * qtd + stream->segments = NULL; + if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) { + GNode *elst; +- gint n_segments; +- gint segment_number, entry_size; ++ guint n_segments; ++ guint segment_number, entry_size; + guint64 time; + GstClockTime stime; + const guint8 *buffer; +@@ -10783,7 +10783,7 @@ qtdemux_parse_stereo_svmi_atom (GstQTDem + /*parse svmi header if existing */ + svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi); + if (svmi) { +- guint len = QT_UINT32 ((guint8 *) svmi->data); ++ guint32 len = QT_UINT32 ((guint8 *) svmi->data); + guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8); + if (!version) { + GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE; +@@ -11190,7 +11190,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + } else { +- gint i, j, start, end; ++ guint i, j, start, end; + + if (len < 94) + goto corrupt_file; +@@ -11306,7 +11306,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + if (pasp) { + const guint8 *pasp_data = (const guint8 *) pasp->data; +- gint len = QT_UINT32 (pasp_data); ++ guint len = QT_UINT32 (pasp_data); + + if (len == 16) { + CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8); +@@ -11322,7 +11322,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + if (fiel) { + const guint8 *fiel_data = (const guint8 *) fiel->data; +- gint len = QT_UINT32 (fiel_data); ++ guint len = QT_UINT32 (fiel_data); + + if (len == 10) { + CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8); +@@ -11332,7 +11332,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + if (colr) { + const guint8 *colr_data = (const guint8 *) colr->data; +- gint len = QT_UINT32 (colr_data); ++ guint len = QT_UINT32 (colr_data); + + if (len == 19 || len == 18) { + guint32 color_type = GST_READ_UINT32_LE (colr_data + 8); +@@ -11369,14 +11369,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_avc1: + case FOURCC_avc3: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *avc_data = stsd_entry_data + 0x56; + + /* find avcC */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (avc_data) <= len) ++ if (QT_UINT32 (avc_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (avc_data) <= len) + size = QT_UINT32 (avc_data) - 0x8; + else + size = len - 0x8; +@@ -11483,14 +11486,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_dvh1: + case FOURCC_dvhe: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *hevc_data = stsd_entry_data + 0x56; + + /* find hevc */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (hevc_data) <= len) ++ if (QT_UINT32 (hevc_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (hevc_data) <= len) + size = QT_UINT32 (hevc_data) - 0x8; + else + size = len - 0x8; +@@ -11546,7 +11552,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + if (glbl) { + guint8 *data; + GstBuffer *buf; +- gint len; ++ guint len; + + GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd"); + data = glbl->data; +@@ -11730,7 +11736,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + /* add codec_data if provided */ + if (prefix) { + GstBuffer *buf; +- gint len; ++ guint len; + + GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd"); + data = prefix->data; +@@ -11752,7 +11758,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + GstBuffer *buf; + GstBuffer *seqh = NULL; + const guint8 *gamma_data = NULL; +- gint len = QT_UINT32 (stsd_data); /* FIXME review - why put the whole stsd in codec data? */ ++ guint len = QT_UINT32 (stsd_data); /* FIXME review - why put the whole stsd in codec data? */ + + qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data, + &seqh); +@@ -11904,14 +11910,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_vc_1: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *vc1_data = stsd_entry_data + 0x56; + + /* find dvc1 */ + while (len >= 8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (vc1_data) <= len) ++ if (QT_UINT32 (vc1_data) <= 8) ++ size = 0; ++ else if (QT_UINT32 (vc1_data) <= len) + size = QT_UINT32 (vc1_data) - 8; + else + size = len - 8; +@@ -11943,14 +11952,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_av01: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *av1_data = stsd_entry_data + 0x56; + + /* find av1C */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (av1_data) <= len) ++ if (QT_UINT32 (av1_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (av1_data) <= len) + size = QT_UINT32 (av1_data) - 0x8; + else + size = len - 0x8; +@@ -12022,14 +12034,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + * vp08, vp09, and vp10 fourcc. */ + case FOURCC_vp09: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *vpcc_data = stsd_entry_data + 0x56; + + /* find vpcC */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (vpcc_data) <= len) ++ if (QT_UINT32 (vpcc_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (vpcc_data) <= len) + size = QT_UINT32 (vpcc_data) - 0x8; + else + size = len - 0x8; +@@ -12177,7 +12192,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + } else if (stream->subtype == FOURCC_soun) { + GNode *wave; +- int version, samplesize; ++ guint version, samplesize; + guint16 compression_id; + gboolean amrwb = FALSE; + +@@ -12492,7 +12507,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_wma_: + { +- gint len = QT_UINT32 (stsd_entry_data) - offset; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= offset ? 0 : len - offset; + const guint8 *wfex_data = stsd_entry_data + offset; + const gchar *codec_name = NULL; + gint version = 1; +@@ -12516,9 +12532,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + /* find wfex */ + while (len >= 8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (wfex_data) <= len) ++ if (QT_UINT32 (wfex_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (wfex_data) <= len) + size = QT_UINT32 (wfex_data) - 8; + else + size = len - 8; diff --git a/CVE-2024-47545-pre2.patch b/CVE-2024-47545-pre2.patch new file mode 100644 index 0000000..90a2e26 --- /dev/null +++ b/CVE-2024-47545-pre2.patch @@ -0,0 +1,116 @@ +From d4bab55077c6a77bd80cb12a8b0d28020ef412a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Tue, 24 Sep 2024 09:50:34 +0300 +Subject: [PATCH] qtdemux: Skip zero-sized boxes instead of stopping to look at + further boxes + +A zero-sized box is not really a problem and can be skipped to look at any +possibly following ones. + +BMD ATEM devices specifically write a zero-sized bmdc box in the sample +description, followed by the avcC box in case of h264. Previously the avcC box +would simply not be read at all and the file would be unplayable. + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 54 ++++++++++++------- + 1 file changed, 36 insertions(+), 18 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -11384,9 +11384,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ avc_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (avc_data + 0x4)) { + case FOURCC_avcC: +@@ -11501,9 +11504,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ hevc_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (hevc_data + 0x4)) { + case FOURCC_hvcC: +@@ -11925,9 +11931,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ vc1_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (vc1_data + 0x4)) { + case GST_MAKE_FOURCC ('d', 'v', 'c', '1'): +@@ -11967,9 +11976,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ av1_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (av1_data + 0x4)) { + case FOURCC_av1C: +@@ -12049,9 +12061,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ vpcc_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (vpcc_data + 0x4)) { + case FOURCC_vpcC: +@@ -12541,9 +12556,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ wfex_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (wfex_data + 4)) { + case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'): diff --git a/CVE-2024-47545.patch b/CVE-2024-47545.patch new file mode 100644 index 0000000..4ceeb3e --- /dev/null +++ b/CVE-2024-47545.patch @@ -0,0 +1,444 @@ +Backport of: + +From fe9d5d37234aca04fef7248184177168905a7a69 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Fri, 27 Sep 2024 00:12:57 +0300 +Subject: [PATCH] qtdemux: Fix length checks and offsets in stsd entry parsing + +Thanks to Antonio Morales for finding and reporting the issue. + +Fixes GHSL-2024-242 +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3845 + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 218 +++++++----------- + 1 file changed, 79 insertions(+), 139 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -11369,43 +11369,35 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_avc1: + case FOURCC_avc3: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *avc_data = stsd_entry_data + 0x56; + + /* find avcC */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (avc_data); + +- if (QT_UINT32 (avc_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (avc_data) <= len) +- size = QT_UINT32 (avc_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- avc_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (avc_data + 0x4)) { ++ switch (QT_FOURCC (avc_data + 4)) { + case FOURCC_avcC: + { + /* parse, if found */ + GstBuffer *buf; + ++ if (size < 8 + 1) ++ break; ++ + GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd"); + + /* First 4 bytes are the length of the atom, the next 4 bytes + * are the fourcc, the next 1 byte is the version, and the + * subsequent bytes are profile_tier_level structure like data. */ + gst_codec_utils_h264_caps_set_level_and_profile (entry->caps, +- avc_data + 8 + 1, size - 1); +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, avc_data + 0x8, size); ++ avc_data + 8 + 1, size - 8 - 1); ++ buf = gst_buffer_new_and_alloc (size - 8); ++ gst_buffer_fill (buf, 0, avc_data + 8, size - 8); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11416,6 +11408,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + { + GstBuffer *buf; + ++ if (size < 8 + 40 + 1) ++ break; ++ + GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd"); + + /* First 4 bytes are the length of the atom, the next 4 bytes +@@ -11423,17 +11418,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + * next 1 byte is the version, and the + * subsequent bytes are sequence parameter set like data. */ + +- size -= 40; /* we'll be skipping BITMAPINFOHEADER */ +- if (size > 1) { +- gst_codec_utils_h264_caps_set_level_and_profile +- (entry->caps, avc_data + 8 + 40 + 1, size - 1); ++ gst_codec_utils_h264_caps_set_level_and_profile ++ (entry->caps, avc_data + 8 + 40 + 1, size - 8 - 40 - 1); + +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, avc_data + 8 + 40, size); +- gst_caps_set_simple (entry->caps, +- "codec_data", GST_TYPE_BUFFER, buf, NULL); +- gst_buffer_unref (buf); +- } ++ buf = gst_buffer_new_and_alloc (size - 8 - 40); ++ gst_buffer_fill (buf, 0, avc_data + 8 + 40, size - 8 - 40); ++ gst_caps_set_simple (entry->caps, ++ "codec_data", GST_TYPE_BUFFER, buf, NULL); ++ gst_buffer_unref (buf); + break; + } + case FOURCC_btrt: +@@ -11441,11 +11433,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + guint avg_bitrate, max_bitrate; + + /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */ +- if (size < 12) ++ if (size < 8 + 12) + break; + +- max_bitrate = QT_UINT32 (avc_data + 0xc); +- avg_bitrate = QT_UINT32 (avc_data + 0x10); ++ max_bitrate = QT_UINT32 (avc_data + 8 + 4); ++ avg_bitrate = QT_UINT32 (avc_data + 8 + 8); + + if (!max_bitrate && !avg_bitrate) + break; +@@ -11477,8 +11469,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + +- len -= size + 8; +- avc_data += size + 8; ++ len -= size; ++ avc_data += size; + } + + break; +@@ -11489,44 +11481,36 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_dvh1: + case FOURCC_dvhe: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *hevc_data = stsd_entry_data + 0x56; + + /* find hevc */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (hevc_data); + +- if (QT_UINT32 (hevc_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (hevc_data) <= len) +- size = QT_UINT32 (hevc_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- hevc_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (hevc_data + 0x4)) { ++ switch (QT_FOURCC (hevc_data + 4)) { + case FOURCC_hvcC: + { + /* parse, if found */ + GstBuffer *buf; + ++ if (size < 8 + 1) ++ break; ++ + GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd"); + + /* First 4 bytes are the length of the atom, the next 4 bytes + * are the fourcc, the next 1 byte is the version, and the + * subsequent bytes are sequence parameter set like data. */ + gst_codec_utils_h265_caps_set_level_tier_and_profile +- (entry->caps, hevc_data + 8 + 1, size - 1); ++ (entry->caps, hevc_data + 8 + 1, size - 8 - 1); + +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, hevc_data + 0x8, size); ++ buf = gst_buffer_new_and_alloc (size - 8); ++ gst_buffer_fill (buf, 0, hevc_data + 8, size - 8); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11535,8 +11519,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + default: + break; + } +- len -= size + 8; +- hevc_data += size + 8; ++ len -= size; ++ hevc_data += size; + } + break; + } +@@ -11916,36 +11900,25 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_vc_1: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *vc1_data = stsd_entry_data + 0x56; + + /* find dvc1 */ + while (len >= 8) { +- guint size; ++ guint32 size = QT_UINT32 (vc1_data); + +- if (QT_UINT32 (vc1_data) <= 8) +- size = 0; +- else if (QT_UINT32 (vc1_data) <= len) +- size = QT_UINT32 (vc1_data) - 8; +- else +- size = len - 8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- vc1_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (vc1_data + 0x4)) { ++ switch (QT_FOURCC (vc1_data + 4)) { + case GST_MAKE_FOURCC ('d', 'v', 'c', '1'): + { + GstBuffer *buf; + + GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd"); +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, vc1_data + 8, size); ++ buf = gst_buffer_new_and_alloc (size - 8); ++ gst_buffer_fill (buf, 0, vc1_data + 8, size - 8); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11954,36 +11927,25 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + default: + break; + } +- len -= size + 8; +- vc1_data += size + 8; ++ len -= size; ++ vc1_data += size; + } + break; + } + case FOURCC_av01: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *av1_data = stsd_entry_data + 0x56; + + /* find av1C */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (av1_data); + +- if (QT_UINT32 (av1_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (av1_data) <= len) +- size = QT_UINT32 (av1_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- av1_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (av1_data + 0x4)) { ++ switch (QT_FOURCC (av1_data + 4)) { + case FOURCC_av1C: + { + /* parse, if found */ +@@ -11994,7 +11956,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + "found av1C codec_data in stsd of size %d", size); + + /* not enough data, just ignore and hope for the best */ +- if (size < 5) ++ if (size < 8 + 5) + break; + + /* Content is: +@@ -12020,10 +11982,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + "presentation-delay", G_TYPE_INT, + (gint) (pres_delay_field & 0x0F) + 1, NULL); + } +- if (size > 5) { +- buf = gst_buffer_new_and_alloc (size - 5); ++ if (size > 8 + 5) { ++ buf = gst_buffer_new_and_alloc (size - 8 - 5); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER); +- gst_buffer_fill (buf, 0, av1_data + 13, size - 5); ++ gst_buffer_fill (buf, 0, av1_data + 13, size - 8 - 5); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -12034,8 +11996,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + +- len -= size + 8; +- av1_data += size + 8; ++ len -= size; ++ av1_data += size; + } + + break; +@@ -12046,29 +12008,18 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + * vp08, vp09, and vp10 fourcc. */ + case FOURCC_vp09: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *vpcc_data = stsd_entry_data + 0x56; + + /* find vpcC */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (vpcc_data); + +- if (QT_UINT32 (vpcc_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (vpcc_data) <= len) +- size = QT_UINT32 (vpcc_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- vpcc_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (vpcc_data + 0x4)) { ++ switch (QT_FOURCC (vpcc_data + 4)) { + case FOURCC_vpcC: + { + const gchar *profile_str = NULL; +@@ -12084,7 +12035,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + /* the meaning of "size" is length of the atom body, excluding + * atom length and fourcc fields */ +- if (size < 12) ++ if (size < 8 + 12) + break; + + /* Content is: +@@ -12190,8 +12141,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + +- len -= size + 8; +- vpcc_data += size + 8; ++ len -= size; ++ vpcc_data += size; + } + + break; +@@ -12522,7 +12473,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_wma_: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= offset ? 0 : len - offset; + const guint8 *wfex_data = stsd_entry_data + offset; + const gchar *codec_name = NULL; +@@ -12547,21 +12498,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + /* find wfex */ + while (len >= 8) { +- guint size; ++ guint32 size = QT_UINT32 (wfex_data); + +- if (QT_UINT32 (wfex_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (wfex_data) <= len) +- size = QT_UINT32 (wfex_data) - 8; +- else +- size = len - 8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- wfex_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + + switch (QT_FOURCC (wfex_data + 4)) { + case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'): +@@ -12606,12 +12546,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + "width", G_TYPE_INT, wfex.wBitsPerSample, + "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL); + +- if (size > wfex.cbSize) { ++ if (size > 8 + wfex.cbSize) { + GstBuffer *buf; + +- buf = gst_buffer_new_and_alloc (size - wfex.cbSize); ++ buf = gst_buffer_new_and_alloc (size - 8 - wfex.cbSize); + gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize, +- size - wfex.cbSize); ++ size - 8 - wfex.cbSize); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -12628,8 +12568,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + default: + break; + } +- len -= size + 8; +- wfex_data += size + 8; ++ len -= size; ++ wfex_data += size; + } + break; + } diff --git a/gstreamer1-plugins-good.spec b/gstreamer1-plugins-good.spec index 8897dd8..ec01114 100644 --- a/gstreamer1-plugins-good.spec +++ b/gstreamer1-plugins-good.spec @@ -3,7 +3,7 @@ Name: gstreamer1-plugins-good Version: 1.20.3 -Release: 3 +Release: 4 Summary: GStreamer plugins with good code and licensing License: LGPLv2+ URL: http://gstreamer.freedesktop.org/ @@ -33,6 +33,10 @@ Patch19: CVE-2024-47598.patch Patch20: matroskademux-Fix-off-by-one-when-parsing-multi-channel-WavPack.patch Patch21: qtdemux-Do-not-iterate-over-all-trun-entries-if-none.patch Patch22: qtdemux-Fix-debug-output-during-trun-parsing.patch +Patch23: CVE-2024-47545-pre1.patch +Patch24: CVE-2024-47545-pre2.patch +Patch25: CVE-2024-47545.patch +Patch26: CVE-2024-47544.patch BuildRequires: meson >= 0.48.0 BuildRequires: gcc @@ -198,6 +202,9 @@ install -p -D %{SOURCE1} %{buildroot}%{_metainfodir}/gstreamer-good.appdata.xml %endif %changelog +* Fri Dec 20 2024 yaoxin - 1.20.3-4 +- Fix CVE-2024-47544 and CVE-2024-47545 + * Wed Dec 18 2024 yaoxin - 1.20.3-3 - Fix cves: CVE-2024-47606,CVE-2024-47599,CVE-2024-47613,CVE-2024-47775