Fixes: heap array overread Fixes: asan_heap-oob_149b2bc_6577_m1.mxg Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.2-rc1
| @@ -119,7 +119,7 @@ read_header: | |||||
| 8 * FFMIN(field_size, buf_end - buf_ptr - sos_offs)); | 8 * FFMIN(field_size, buf_end - buf_ptr - sos_offs)); | ||||
| s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16)); | s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16)); | ||||
| s->start_code = SOS; | s->start_code = SOS; | ||||
| if (ff_mjpeg_decode_sos(s, NULL, NULL) < 0 && | |||||
| if (ff_mjpeg_decode_sos(s, NULL, 0, NULL) < 0 && | |||||
| (avctx->err_recognition & AV_EF_EXPLODE)) | (avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| @@ -1100,6 +1100,7 @@ static void shift_output(MJpegDecodeContext *s, uint8_t *ptr, int linesize) | |||||
| static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, | static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, | ||||
| int Al, const uint8_t *mb_bitmask, | int Al, const uint8_t *mb_bitmask, | ||||
| int mb_bitmask_size, | |||||
| const AVFrame *reference) | const AVFrame *reference) | ||||
| { | { | ||||
| int i, mb_x, mb_y; | int i, mb_x, mb_y; | ||||
| @@ -1109,8 +1110,13 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, | |||||
| GetBitContext mb_bitmask_gb; | GetBitContext mb_bitmask_gb; | ||||
| int bytes_per_pixel = 1 + (s->bits > 8); | int bytes_per_pixel = 1 + (s->bits > 8); | ||||
| if (mb_bitmask) | |||||
| if (mb_bitmask) { | |||||
| if (mb_bitmask_size != (s->mb_width * s->mb_height + 7)>>3) { | |||||
| av_log(s->avctx, AV_LOG_ERROR, "mb_bitmask_size mismatches\n"); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height); | init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height); | ||||
| } | |||||
| s->restart_count = 0; | s->restart_count = 0; | ||||
| @@ -1265,7 +1271,7 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, | |||||
| } | } | ||||
| int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, | int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, | ||||
| const AVFrame *reference) | |||||
| int mb_bitmask_size, const AVFrame *reference) | |||||
| { | { | ||||
| int len, nb_components, i, h, v, predictor, point_transform; | int len, nb_components, i, h, v, predictor, point_transform; | ||||
| int index, id, ret; | int index, id, ret; | ||||
| @@ -1397,7 +1403,7 @@ next_field: | |||||
| } else { | } else { | ||||
| if ((ret = mjpeg_decode_scan(s, nb_components, | if ((ret = mjpeg_decode_scan(s, nb_components, | ||||
| prev_shift, point_transform, | prev_shift, point_transform, | ||||
| mb_bitmask, reference)) < 0) | |||||
| mb_bitmask, mb_bitmask_size, reference)) < 0) | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| } | } | ||||
| @@ -1963,7 +1969,7 @@ eoi_parser: | |||||
| goto the_end; | goto the_end; | ||||
| case SOS: | case SOS: | ||||
| s->cur_scan++; | s->cur_scan++; | ||||
| if ((ret = ff_mjpeg_decode_sos(s, NULL, NULL)) < 0 && | |||||
| if ((ret = ff_mjpeg_decode_sos(s, NULL, 0, NULL)) < 0 && | |||||
| (avctx->err_recognition & AV_EF_EXPLODE)) | (avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| goto fail; | goto fail; | ||||
| break; | break; | ||||
| @@ -137,7 +137,8 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s); | |||||
| int ff_mjpeg_decode_dht(MJpegDecodeContext *s); | int ff_mjpeg_decode_dht(MJpegDecodeContext *s); | ||||
| int ff_mjpeg_decode_sof(MJpegDecodeContext *s); | int ff_mjpeg_decode_sof(MJpegDecodeContext *s); | ||||
| int ff_mjpeg_decode_sos(MJpegDecodeContext *s, | int ff_mjpeg_decode_sos(MJpegDecodeContext *s, | ||||
| const uint8_t *mb_bitmask, const AVFrame *reference); | |||||
| const uint8_t *mb_bitmask,int mb_bitmask_size, | |||||
| const AVFrame *reference); | |||||
| int ff_mjpeg_find_marker(MJpegDecodeContext *s, | int ff_mjpeg_find_marker(MJpegDecodeContext *s, | ||||
| const uint8_t **buf_ptr, const uint8_t *buf_end, | const uint8_t **buf_ptr, const uint8_t *buf_end, | ||||
| const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size); | const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size); | ||||
| @@ -295,11 +295,11 @@ static int mxpeg_decode_frame(AVCodecContext *avctx, | |||||
| AV_GET_BUFFER_FLAG_REF)) < 0) | AV_GET_BUFFER_FLAG_REF)) < 0) | ||||
| return ret; | return ret; | ||||
| ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, reference_ptr); | |||||
| ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, s->bitmask_size, reference_ptr); | |||||
| if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) | if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| return ret; | return ret; | ||||
| } else { | } else { | ||||
| ret = ff_mjpeg_decode_sos(jpg, NULL, NULL); | |||||
| ret = ff_mjpeg_decode_sos(jpg, NULL, 0, NULL); | |||||
| if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) | if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| return ret; | return ret; | ||||
| } | } | ||||