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.
> also is this not also needed in mjpeg_decode_scan_progressive_ac() ?
I don't think so.
While mjpeg_decode_scan calculates the y offset with '(v * mb_y + y) * 8',
which can be larger than chroma_height (and even s->height),
mjpeg_decode_scan_progressive_ac uses for some reason just 'mb_y * 8',
which can't be larger than chroma_height, as far as I can tell.
Best regards,
Andreas
>From 153494b62cf3e143a90eb8f02fdef5e017163f0b Mon Sep 17 00:00:00 2001
From: Andreas Cadhalpun <[email protected]>
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 <[email protected]>
---
libavcodec/mjpegdec.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index cfc59ac..8dfcae0 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 ? chroma_width : s->width)
+ && 8*(v * mb_y + y) < (c ? chroma_height : s->height)) {
ptr = data[c] + block_offset;
} else
ptr = NULL;
--
2.6.2
_______________________________________________
ffmpeg-devel mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel