There's a race condition in gsttagdemux.c between typefinding and the
end-of-stream event. If TYPE_FIND_MAX_SIZE is exceeded,
demux->priv->collect is set to NULL and an error is returned. However,
the end-of-stream event causes one last attempt at typefinding to occur.
This leads to gst_tag_demux_trim_buffer() being called with the NULL
demux->priv->collect buffer which it attempts to dereference, resulting
in a segfault.
The malicious MP3 can be created by:
printf "\x49\x44\x33\x04\x00\x00\x00\x00\x00\x00%s", \
"$(dd if=/dev/urandom bs=1K count=200)" > malicious.mp3
This creates a valid ID3 header which gets us as far as typefinding. The
crash can then be reproduced with the following pipeline:
gst-launch-1.0 -e filesrc location=malicious.mp3 ! queue ! decodebin ! audioconvert ! vorbisenc ! oggmux ! filesink location=malicious.ogg
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/967
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1620>
/* Trim the buffer and adjust offset for typefinding */
typefind_buf = demux->priv->collect;
- gst_buffer_ref (typefind_buf);
- if (!gst_tag_demux_trim_buffer (demux, &typefind_buf, &typefind_size))
- return GST_FLOW_EOS;
+ if (typefind_buf) {
+ gst_buffer_ref (typefind_buf);
+ if (!gst_tag_demux_trim_buffer (demux, &typefind_buf, &typefind_size))
+ return GST_FLOW_EOS;
+ }
if (typefind_buf == NULL)
break; /* Still need more data */