From 57efb6d94ceb42780577210616d30c98d89f6765 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 9 Jul 2013 14:59:33 +0200 Subject: [PATCH 1/7] qdm2: Conceal broken samples Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit 4ecdb5ed44591aba8a0ddb7d443cace836f761f6) Signed-off-by: Luca Barbato Conflicts: libavcodec/qdm2.c --- libavcodec/qdm2.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 365f717bcc..1a076236cf 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -498,7 +498,8 @@ static void build_sb_samples_from_noise (QDM2Context *q, int sb) * @param channels number of channels * @param coding_method q->coding_method[0][0][0] */ -static void fix_coding_method_array (int sb, int channels, sb_int8_array coding_method) +static int fix_coding_method_array(int sb, int channels, + sb_int8_array coding_method) { int j,k; int ch; @@ -507,8 +508,10 @@ static void fix_coding_method_array (int sb, int channels, sb_int8_array coding_ for (ch = 0; ch < channels; ch++) { for (j = 0; j < 64; ) { - if((coding_method[ch][sb][j] - 8) > 22) { - run = 1; + if (coding_method[ch][sb][j] < 8) + return -1; + if ((coding_method[ch][sb][j] - 8) > 22) { + run = 1; case_val = 8; } else { switch (switchtable[coding_method[ch][sb][j]-8]) { @@ -533,6 +536,7 @@ static void fix_coding_method_array (int sb, int channels, sb_int8_array coding_ j += run; } } + return 0; } @@ -802,7 +806,11 @@ static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int l if (q->coding_method[1][sb][j] > q->coding_method[0][sb][j]) q->coding_method[0][sb][j] = q->coding_method[1][sb][j]; - fix_coding_method_array(sb, q->nb_channels, q->coding_method); + if (fix_coding_method_array(sb, q->nb_channels, + q->coding_method)) { + build_sb_samples_from_noise(q, sb); + continue; + } channels = 1; } From 195b9f290cb61f2af1204970c8088c941647e90a Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Jun 2013 07:26:48 +0200 Subject: [PATCH 2/7] iff: Do not read over the source buffer Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit 7d65e960c72f36b73ae7fe84f8e427d758e61da9) Signed-off-by: Luca Barbato Conflicts: libavcodec/iff.c --- libavcodec/iff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/iff.c b/libavcodec/iff.c index 41e7b5939f..b931e40213 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -271,7 +271,7 @@ static int decode_frame_ilbm(AVCodecContext *avctx, if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { - for(y = 0; y < avctx->height; y++ ) { + for (y = 0; y < avctx->height && buf < buf_end; y++ ) { uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ]; memset(row, 0, avctx->width); for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) { From 9c05debdcd75fe3bcfbec3f200334f404ebcea56 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Jun 2013 05:29:54 +0200 Subject: [PATCH 3/7] wmavoice: conceal clearly corrupted blocks Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit d14a26edb7c4487df581f11e5c6911dc0e623d08) Signed-off-by: Luca Barbato --- libavcodec/wmavoice.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index 86e6996e1a..41a9ea3bb8 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -1046,9 +1046,10 @@ static void aw_parse_coords(WMAVoiceContext *s, GetBitContext *gb, * @param gb bit I/O context * @param block_idx block index in frame [0, 1] * @param fcb structure containing fixed codebook vector info + * @return -1 on error, 0 otherwise */ -static void aw_pulse_set2(WMAVoiceContext *s, GetBitContext *gb, - int block_idx, AMRFixed *fcb) +static int aw_pulse_set2(WMAVoiceContext *s, GetBitContext *gb, + int block_idx, AMRFixed *fcb) { uint16_t use_mask_mem[9]; // only 5 are used, rest is padding uint16_t *use_mask = use_mask_mem + 2; @@ -1110,7 +1111,7 @@ static void aw_pulse_set2(WMAVoiceContext *s, GetBitContext *gb, else if (use_mask[2]) idx = 0x2F; else if (use_mask[3]) idx = 0x3F; else if (use_mask[4]) idx = 0x4F; - else return; + else return -1; idx -= av_log2_16bit(use_mask[idx >> 4]); } if (use_mask[idx >> 4] & (0x8000 >> (idx & 15))) { @@ -1127,6 +1128,7 @@ static void aw_pulse_set2(WMAVoiceContext *s, GetBitContext *gb, /* set offset for next block, relative to start of that block */ n = (MAX_FRAMESIZE / 2 - start_off) % fcb->pitch_lag; s->aw_next_pulse_off_cache = n ? fcb->pitch_lag - n : 0; + return 0; } /** @@ -1289,7 +1291,18 @@ static void synth_block_fcb_acb(WMAVoiceContext *s, GetBitContext *gb, * (fixed) codebook pulses of the speech signal. */ if (frame_desc->fcb_type == FCB_TYPE_AW_PULSES) { aw_pulse_set1(s, gb, block_idx, &fcb); - aw_pulse_set2(s, gb, block_idx, &fcb); + if (aw_pulse_set2(s, gb, block_idx, &fcb)) { + /* Conceal the block with silence and return. + * Skip the correct amount of bits to read the next + * block from the correct offset. */ + int r_idx = pRNG(s->frame_cntr, block_idx, size); + + for (n = 0; n < size; n++) + excitation[n] = + wmavoice_std_codebook[r_idx + n] * s->silence_gain; + skip_bits(gb, 7 + 1); + return; + } } else /* FCB_TYPE_EXC_PULSES */ { int offset_nbits = 5 - frame_desc->log_n_blocks; From 9c3c08ba984ab0447a65a1e8417f01bea4dccf70 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 29 Jun 2013 06:37:32 +0200 Subject: [PATCH 4/7] pcx: Do not overread source buffer in pcx_rle_decode Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit 3abde1a3b49cf299f2aae4eaae6b6cb5270bdc22) Signed-off-by: Luca Barbato --- libavcodec/pcx.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/libavcodec/pcx.c b/libavcodec/pcx.c index 7eb1daaa7a..0377b9298c 100644 --- a/libavcodec/pcx.c +++ b/libavcodec/pcx.c @@ -43,16 +43,19 @@ static av_cold int pcx_init(AVCodecContext *avctx) { /** * @return advanced src pointer */ -static const uint8_t *pcx_rle_decode(const uint8_t *src, uint8_t *dst, - unsigned int bytes_per_scanline, int compressed) { +static const uint8_t *pcx_rle_decode(const uint8_t *src, + const uint8_t *end, + uint8_t *dst, + unsigned int bytes_per_scanline, + int compressed) { unsigned int i = 0; unsigned char run, value; if (compressed) { - while (i= 0xc0) { + if (value >= 0xc0 && src < end) { run = value & 0x3f; value = *src++; } @@ -87,6 +90,7 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, bytes_per_scanline; uint8_t *ptr; + const uint8_t *buf_end = buf + buf_size; uint8_t const *bufstart = buf; uint8_t *scanline; int ret = -1; @@ -115,7 +119,8 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, nplanes = buf[65]; bytes_per_scanline = nplanes * bytes_per_line; - if (bytes_per_scanline < w * bits_per_pixel * nplanes / 8) { + if (bytes_per_scanline < w * bits_per_pixel * nplanes / 8 || + (!compressed && bytes_per_scanline > buf_size / h)) { av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); return -1; } @@ -163,7 +168,8 @@ static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, if (nplanes == 3 && bits_per_pixel == 8) { for (y=0; y> (x&7), v = 0; From 47baf9ca87347a8f7516a45f446c7756ad6cb89d Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 10 Jul 2013 04:35:34 +0200 Subject: [PATCH 5/7] mlpdec: Do not set invalid context in read_restart_header The faulty values rippled further down the codepath causing a hard-to-track segfault in the assembly code. Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit e9d394f3fad7e8fd8fc80e3b33cb045bbaceb446) Signed-off-by: Luca Barbato Conflicts: libavcodec/mlpdec.c --- libavcodec/mlpdec.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 357e28728d..e74b20269a 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -346,9 +346,10 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, uint8_t checksum; uint8_t lossless_check; int start_count = get_bits_count(gbp); - const int max_matrix_channel = m->avctx->codec_id == CODEC_ID_MLP - ? MAX_MATRIX_CHANNEL_MLP - : MAX_MATRIX_CHANNEL_TRUEHD; + int min_channel, max_channel, max_matrix_channel; + const int std_max_matrix_channel = m->avctx->codec_id == CODEC_ID_MLP + ? MAX_MATRIX_CHANNEL_MLP + : MAX_MATRIX_CHANNEL_TRUEHD; sync_word = get_bits(gbp, 13); @@ -367,18 +368,18 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, skip_bits(gbp, 16); /* Output timestamp */ - s->min_channel = get_bits(gbp, 4); - s->max_channel = get_bits(gbp, 4); - s->max_matrix_channel = get_bits(gbp, 4); + min_channel = get_bits(gbp, 4); + max_channel = get_bits(gbp, 4); + max_matrix_channel = get_bits(gbp, 4); - if (s->max_matrix_channel > max_matrix_channel) { + if (max_matrix_channel > std_max_matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max matrix channel cannot be greater than %d.\n", max_matrix_channel); return AVERROR_INVALIDDATA; } - if (s->max_channel != s->max_matrix_channel) { + if (max_channel != max_matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max channel must be equal max matrix channel.\n"); return AVERROR_INVALIDDATA; @@ -393,15 +394,20 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, return AVERROR_INVALIDDATA; } - if (s->min_channel > s->max_channel) { + if (min_channel > max_channel) { av_log(m->avctx, AV_LOG_ERROR, "Substream min channel cannot be greater than max channel.\n"); return AVERROR_INVALIDDATA; } - if (m->avctx->request_channels > 0 - && s->max_channel + 1 >= m->avctx->request_channels - && substr < m->max_decoded_substream) { + + s->min_channel = min_channel; + s->max_channel = max_channel; + s->max_matrix_channel = max_matrix_channel; + + if (m->avctx->request_channels > 0 && + m->avctx->request_channels <= s->max_channel + 1 && + m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, "Extracting %d channel downmix from substream %d. " "Further substreams will be skipped.\n", From 62c35475396dd0c3afb5d6c66a1245c1a3bbe9b6 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 10 Jul 2013 04:54:49 +0200 Subject: [PATCH 6/7] pcm: always use codec->id instead of codec_id Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit c82da343e635663605bd81c59d872bee3182da73) Signed-off-by: Luca Barbato Conflicts: libavcodec/pcm.c --- libavcodec/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index 1adaf70318..cd44d77000 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -268,7 +268,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, /* av_get_bits_per_sample returns 0 for CODEC_ID_PCM_DVD */ samples_per_block = 1; - if (CODEC_ID_PCM_DVD == avctx->codec_id) { + if (avctx->codec->id == CODEC_ID_PCM_DVD) { if (avctx->bits_per_coded_sample != 20 && avctx->bits_per_coded_sample != 24) { av_log(avctx, AV_LOG_ERROR, "PCM DVD unsupported sample depth\n"); From ce3ce08850f1690dff01d9bb4ed6a4274d52771e Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 10 Jul 2013 18:07:45 +0200 Subject: [PATCH 7/7] dca: Error out on missing DSYNC Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org (cherry picked from commit f261e508459e28beca59868a878e1519a44bb678) Signed-off-by: Luca Barbato --- libavcodec/dca.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/dca.c b/libavcodec/dca.c index a83d082118..61a056e13a 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -1254,6 +1254,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) #endif } else { av_log(s->avctx, AV_LOG_ERROR, "Didn't get subframe DSYNC\n"); + return AVERROR_INVALIDDATA; } }