summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Chadwell <justin.chadwell@pexip.com>2020-07-14 14:24:20 +0100
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2020-09-25 12:41:06 +0000
commit310dec75cd0b630a765ee93c82a473e17fb5dd94 (patch)
treecfd7f7bfd404d7c8143e323ebfdc318a6a155641
parent7241f5d9c21ee3ead0294d6480a6fe5af4bf3b74 (diff)
qtdemux: fix allocation explosion with stsd entries
Previously, the user input for stsd entries is trusted completely, and so a maliciously crafted file could choose the length of the stsd entries arbitrarily and cause qtdemux to try to allocate up to 2GB of memory (half of a 32 bit max int). This patch fixes this by sanity checking the stsd input against the size of the entire stsd atom. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/749>
-rw-r--r--gst/isomp4/qtdemux.c6
-rw-r--r--tests/check/elements/qtdemux.c51
2 files changed, 56 insertions, 1 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index 76924cb9e..9bd299dc7 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -10657,8 +10657,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
- if (stream->stsd_entries_length == 0)
+ /* each stsd entry must contain at least 8 bytes */
+ if (stream->stsd_entries_length == 0
+ || stream->stsd_entries_length > stsd_len / 8) {
+ stream->stsd_entries_length = 0;
goto corrupt_file;
+ }
stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
GST_LOG_OBJECT (qtdemux, "stsd len: %d", stsd_len);
GST_LOG_OBJECT (qtdemux, "stsd entry count: %u", stsd_entry_count);
diff --git a/tests/check/elements/qtdemux.c b/tests/check/elements/qtdemux.c
index cd9dc6950..3ab695d3e 100644
--- a/tests/check/elements/qtdemux.c
+++ b/tests/check/elements/qtdemux.c
@@ -123,6 +123,56 @@ GST_START_TEST (test_qtdemux_fuzzed0)
GST_END_TEST;
+GST_START_TEST (test_qtdemux_fuzzed1)
+{
+ GstHarness *h;
+ GstBuffer *buf;
+ guchar *fuzzed_qtdemux;
+ gsize fuzzed_qtdemux_len;
+
+ /* The goal of this test is to check that qtdemux can properly handle
+ * a stream that claims it contains more stsd entries than it can possibly have,
+ * by correctly identifying the case and erroring out appropriately.
+ */
+
+ h = gst_harness_new_parse ("qtdemux");
+ gst_harness_set_src_caps_str (h, "video/quicktime");
+
+ fuzzed_qtdemux =
+ g_base64_decode
+ ("AAAAIGZ0eXBtcDQyAAAAAG1wNDJtcDQxaXNvbWlzbzIAAAAIZnJlZQAAAMltZGF0AAAADGdCwAyV"
+ "oQkgHhEI1AAAAARozjyAAAAAIWW4BA5///wRRQAfHAxwABAJkxWTk6xWuuuupaupa6668AAAABJB"
+ "4CBX8Zd3d3d3d3d3eJ7E8ZAAAABWQeBAO+opFAYoDFAYoDFAYkeKAzx4oDFAYkcPHBQGePPHF6jj"
+ "HP0Qdj/og7H/SHY/6jsf9R2P+o7H/Udj/qOx/1HY/6jsf9R2P+o7H/Udj/qOx/1HY/AAAAAGQeBg"
+ "O8IwAAAABkHggDvCMAAAA1dtb292AAAAbG12aGQAAAAA1lbpxdZW6cYAAAfQAAAH0AABAAABAAAA"
+ "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAACAAACpnRyYWsAAABcdGtoZAAAAAfWVunF1lbpxgAAAAEAAAAAAAAH0AAA"
+ "AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAQAAAAEA"
+ "AAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAAAAAAAEAAAAAAeFtZGlhAAAAIG1kaGQAAAAA"
+ "1lbpxdZW6cYAAAH0AAAB9FXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVv"
+ "SGFuZGxlcgAAAAGMbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAA"
+ "AAABAAAADHVybCAAAAABAAABTHN0YmwAAADAc3RzZAAAAADv/wABAAAAsGF2YzEAAAAAAAAAAQAA"
+ "AAAAAAAAAAAAAAAAAAAAQABAAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAY//8AAAAjYXZjQwFCwAz/4QAMZ0LADJWhCSAeEQjUAQAEaM48gAAAABRidHJ0AAAA"
+ "AAAAAAAAAAYIAAAAE2NvbHJuY2x4AAYAAQAGAAAAABBwYXNwAAAAAQAAAAEAAAAYc3R0cwAAAAAA"
+ "AAABAAAABQAAAGQAAAAUc3RzcwAAAAAAAAABAAAAAQAAABxzdHNjAAAAAAAAAAEAAAABAAAABQAA"
+ "AAEAAAAoc3RzegAAAAAAAAAAAAAABQAAAD0AAAAWAAAAWgAAAAoAAAAKAAAAFHN0Y28AAAAAAAAA"
+ "AQAAADAAAAA9dWR0YQAAADVtZXRhAAAAAAAAACFoZGxyAAAAAG1obHJtZGlyAAAAAAAAAAAAAAAA"
+ "AAAAAAhpbHN0AAAAPXVkdGEAAAA1bWV0YQAAAAAAAAAhaGRscgAAAABtaGxybWRpcgAAAAAAAAAA"
+ "AAAAAAAAAAAIaWxzdA==", &fuzzed_qtdemux_len);
+
+ buf = gst_buffer_new_and_alloc (fuzzed_qtdemux_len);
+ gst_buffer_fill (buf, 0, fuzzed_qtdemux, fuzzed_qtdemux_len);
+ fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
+
+ fail_unless (gst_harness_buffers_received (h) == 0);
+
+ g_free (fuzzed_qtdemux);
+ gst_harness_teardown (h);
+}
+
+GST_END_TEST;
+
GST_START_TEST (test_qtdemux_input_gap)
{
GstElement *qtdemux;
@@ -698,6 +748,7 @@ qtdemux_suite (void)
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_qtdemux_fuzzed0);
+ tcase_add_test (tc_chain, test_qtdemux_fuzzed1);
tcase_add_test (tc_chain, test_qtdemux_input_gap);
tcase_add_test (tc_chain, test_qtdemux_duplicated_moov);
tcase_add_test (tc_chain, test_qtdemux_stream_change);