jpegdec: decode the correct number of lines for interlaced frames

For interlaced jpeg, gst_jpeg_dec_decode_direct() is called twice, once for each
field. In this case, stride[n] is plane_stride[n] * 2 to ensure that only every
other line is written. So the loop must stop at height / num_fields.

If the frame is really interlaced then continuing beyound this, is not harmful,
because jpeg_read_raw_data() will do nothing and return 0, so am info message is
printed.

However, if the frame is not actually interlaced, just misdetected as interlaced
then there is still data available from the second half of the frame. Now
line[0][j] is set to the scratch buffer. If the scratch buffer is not allocated
(because the height is a multiple of v_samp[0] * DCTSIZE) then the result is a
segfault due to a null-pointer dereference.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4717>
This commit is contained in:
Michael Olbrich 2020-08-31 16:12:33 +02:00 committed by Tim-Philipp Müller
parent d93f0a51c2
commit b4330c730b

View file

@ -880,7 +880,7 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
gint lines, v_samp[3];
guchar *base[3], *last[3];
gint stride[3];
guint height, field_height;
guint field_height;
line[0] = y;
line[1] = u;
@ -893,7 +893,7 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
goto format_not_supported;
height = field_height = GST_VIDEO_FRAME_HEIGHT (frame);
field_height = GST_VIDEO_FRAME_HEIGHT (frame);
/* XXX: division by 2 here might not be a good idea yes. But we are doing this
* already in gst_jpeg_dec_handle_frame() for interlaced jpeg */
@ -943,7 +943,7 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
} else
#endif
{
for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
for (i = 0; i < field_height; i += v_samp[0] * DCTSIZE) {
for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
/* Y */
line[0][j] = base[0] + (i + j) * stride[0];