diff options
author | Justin Chadwell <justin.chadwell@pexip.com> | 2020-07-14 14:24:20 +0100 |
---|---|---|
committer | GStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2020-09-25 12:41:06 +0000 |
commit | 310dec75cd0b630a765ee93c82a473e17fb5dd94 (patch) | |
tree | cfd7f7bfd404d7c8143e323ebfdc318a6a155641 | |
parent | 7241f5d9c21ee3ead0294d6480a6fe5af4bf3b74 (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.c | 6 | ||||
-rw-r--r-- | tests/check/elements/qtdemux.c | 51 |
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); |