jpegdec: don't overwrite the last valid line
authorMichael Olbrich <m.olbrich@pengutronix.de>
Wed, 7 Nov 2018 08:00:02 +0000 (09:00 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Sun, 10 Nov 2019 12:50:19 +0000 (12:50 +0000)
If the the height is not a multiple of the macro block size then the memory
of the last line is reused for all extra lines. This is no problem if the
last line is duplicated properly. However, if the extra lines are not
initialized properly during encoding, then the last visible line is
overwritten with undefined data.
Use a extra buffer to avoid this problem.

ext/jpeg/gstjpegdec.c
ext/jpeg/gstjpegdec.h

index 6c55229..bcbad7a 100644 (file)
@@ -894,6 +894,12 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
     }
   }
 
+  if (height % (v_samp[0] * DCTSIZE) && (dec->scratch_size < stride[0])) {
+    g_free (dec->scratch);
+    dec->scratch = g_malloc (stride[0]);
+    dec->scratch_size = stride[0];
+  }
+
   /* let jpeglib decode directly into our final buffer */
   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
 
@@ -902,7 +908,7 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
       /* Y */
       line[0][j] = base[0] + (i + j) * stride[0];
       if (G_UNLIKELY (line[0][j] > last[0]))
-        line[0][j] = last[0];
+        line[0][j] = dec->scratch;
       /* U */
       if (v_samp[1] == v_samp[0]) {
         line[1][j] = base[1] + ((i + j) / 2) * stride[1];
@@ -910,7 +916,7 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
         line[1][j] = base[1] + ((i / 2) + j) * stride[1];
       }
       if (G_UNLIKELY (line[1][j] > last[1]))
-        line[1][j] = last[1];
+        line[1][j] = dec->scratch;
       /* V */
       if (v_samp[2] == v_samp[0]) {
         line[2][j] = base[2] + ((i + j) / 2) * stride[2];
@@ -918,7 +924,7 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame,
         line[2][j] = base[2] + ((i / 2) + j) * stride[2];
       }
       if (G_UNLIKELY (line[2][j] > last[2]))
-        line[2][j] = last[2];
+        line[2][j] = dec->scratch;
     }
 
     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
@@ -1555,5 +1561,9 @@ gst_jpeg_dec_stop (GstVideoDecoder * bdec)
 
   gst_jpeg_dec_free_buffers (dec);
 
+  g_free (dec->scratch);
+  dec->scratch = NULL;
+  dec->scratch_size = 0;
+
   return TRUE;
 }
index e8fa2fc..39c7f28 100644 (file)
@@ -90,6 +90,9 @@ struct _GstJpegDec {
   /* arrays for indirect decoding */
   gboolean idr_width_allocated;
   guchar *idr_y[16],*idr_u[16],*idr_v[16];
+  /* scratch buffer for direct decoding overflow */
+  guchar *scratch;
+  guint scratch_size;
   /* current (parsed) image size */
   guint    rem_img_len;
 };