On 05.12.2015 04:02, Michael Niedermayer wrote:
> On Fri, Dec 04, 2015 at 03:14:21PM +0100, Andreas Cadhalpun wrote:
>> On 03.12.2015 15:48, Michael Niedermayer wrote:
>>> On Wed, Dec 02, 2015 at 10:00:13PM +0100, Andreas Cadhalpun wrote:
>>>> @@ -1293,14 +1296,16 @@ static int mjpeg_decode_scan(MJpegDecodeContext 
>>>> *s, int nb_components, int Ah,
>>>>                  v = s->v_scount[i];
>>>>                  x = 0;
>>>>                  y = 0;
>>>> +                h_shift = c ? chroma_h_shift: 0;
>>>> +                v_shift = c ? chroma_v_shift: 0;
>>>>                  for (j = 0; j < n; j++) {
>>>>                      block_offset = (((linesize[c] * (v * mb_y + y) * 8) +
>>>>                                       (h * mb_x + x) * 8 * 
>>>> bytes_per_pixel) >> s->avctx->lowres);
>>>>  
>>>>                      if (s->interlaced && s->bottom_field)
>>>>                          block_offset += linesize[c] >> 1;
>>>> -                    if (   8*(h * mb_x + x) < s->width
>>>> -                        && 8*(v * mb_y + y) < s->height) {
>>>> +                    if (   8*(h * mb_x + x) < (s->width  + (1 << h_shift) 
>>>> - 1) >> h_shift
>>>> +                        && 8*(v * mb_y + y) < (s->height + (1 << v_shift) 
>>>> - 1) >> v_shift) {
>>>
>>> please move the w/h computation out of the block loop
>>> it stays the same for a component and does not need to be
>>> recalculated
>>> theres a loop above that fills data[] that can probably be used to
>>> fill w/h arrays
>>
>> OK, but since there are only two possible values, I don't think filling
>> arrays is necessary. Attached is an updated patch.
> 
> couldnt there be a alpha plane too ?

Yes, fixed patch attached.
I also tested filling w/h arrays, but that turned out to be slightly slower.

Best regards,
Andreas

>From 7788195340e1d0e1206660f12f003f952da750a6 Mon Sep 17 00:00:00 2001
From: Andreas Cadhalpun <andreas.cadhal...@googlemail.com>
Date: Wed, 2 Dec 2015 21:52:23 +0100
Subject: [PATCH] mjpegdec: consider chroma subsampling in size check

If the chroma components are subsampled, smaller buffers are allocated
for them. In that case the maximal block_offset for the chroma
components is not as large as for the luma component.

This fixes out of bounds writes causing segmentation faults or memory
corruption.

Signed-off-by: Andreas Cadhalpun <andreas.cadhal...@googlemail.com>
---
 libavcodec/mjpegdec.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 4c9c82d..c812b86 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -1246,7 +1246,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
                              int mb_bitmask_size,
                              const AVFrame *reference)
 {
-    int i, mb_x, mb_y;
+    int i, mb_x, mb_y, chroma_h_shift, chroma_v_shift, chroma_width, chroma_height;
     uint8_t *data[MAX_COMPONENTS];
     const uint8_t *reference_data[MAX_COMPONENTS];
     int linesize[MAX_COMPONENTS];
@@ -1263,6 +1263,11 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
 
     s->restart_count = 0;
 
+    av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, &chroma_h_shift,
+                                     &chroma_v_shift);
+    chroma_width  = FF_CEIL_RSHIFT(s->width,  chroma_h_shift);
+    chroma_height = FF_CEIL_RSHIFT(s->height, chroma_v_shift);
+
     for (i = 0; i < nb_components; i++) {
         int c   = s->comp_index[i];
         data[c] = s->picture_ptr->data[c];
@@ -1299,8 +1304,8 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
 
                     if (s->interlaced && s->bottom_field)
                         block_offset += linesize[c] >> 1;
-                    if (   8*(h * mb_x + x) < s->width
-                        && 8*(v * mb_y + y) < s->height) {
+                    if (   8*(h * mb_x + x) < ((c == 1) || (c == 2) ? chroma_width  : s->width)
+                        && 8*(v * mb_y + y) < ((c == 1) || (c == 2) ? chroma_height : s->height)) {
                         ptr = data[c] + block_offset;
                     } else
                         ptr = NULL;
-- 
2.6.2

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to