From: "Ronald S. Bultje" <[email protected]>
WMApro (and all wma variants) actually support 13-bits block sizes, and
thus we should support that also. Some WMA functions do not enforce the
12-bit maximum, which causes crashes when decoding such a file because
it expects bigger buffers, which aren't there, causing overreads/writes
and all kind of bad stuff.
If we get block sizes beyond what the decoder can handle (14 is possible
in wmapro, but decoder doesn't handle it, and wma1/2 only handles up to
11), error out instead of crashing.
---
libavcodec/sinewin.h | 3 ++-
libavcodec/sinewin_tablegen.c | 2 +-
libavcodec/sinewin_tablegen.h | 3 ++-
libavcodec/wma.c | 14 +++++++++++---
libavcodec/wma.h | 5 +++--
libavcodec/wmaprodec.c | 12 ++++++++----
6 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/libavcodec/sinewin.h b/libavcodec/sinewin.h
index eefe5bf..8054191 100644
--- a/libavcodec/sinewin.h
+++ b/libavcodec/sinewin.h
@@ -53,7 +53,8 @@ extern SINETABLE( 512);
extern SINETABLE(1024);
extern SINETABLE(2048);
extern SINETABLE(4096);
+extern SINETABLE(8192);
-extern SINETABLE_CONST float * const ff_sine_windows[13];
+extern SINETABLE_CONST float * const ff_sine_windows[14];
#endif /* AVCODEC_SINEWIN_H */
diff --git a/libavcodec/sinewin_tablegen.c b/libavcodec/sinewin_tablegen.c
index 2f4d1aa..d5e0689 100644
--- a/libavcodec/sinewin_tablegen.c
+++ b/libavcodec/sinewin_tablegen.c
@@ -38,7 +38,7 @@ int main(void)
write_fileheader();
- for (i = 5; i <= 12; i++) {
+ for (i = 5; i <= 13; i++) {
ff_init_ff_sine_windows(i);
printf("SINETABLE(%4i) = {\n", 1 << i);
write_float_array(ff_sine_windows[i], 1 << i);
diff --git a/libavcodec/sinewin_tablegen.h b/libavcodec/sinewin_tablegen.h
index 720f1ab..7d92026 100644
--- a/libavcodec/sinewin_tablegen.h
+++ b/libavcodec/sinewin_tablegen.h
@@ -38,6 +38,7 @@ SINETABLE( 512);
SINETABLE(1024);
SINETABLE(2048);
SINETABLE(4096);
+SINETABLE(8192);
#else
#include "libavcodec/sinewin_tables.h"
#endif
@@ -45,7 +46,7 @@ SINETABLE(4096);
SINETABLE_CONST float * const ff_sine_windows[] = {
NULL, NULL, NULL, NULL, NULL, // unused
ff_sine_32 , ff_sine_64 ,
- ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024, ff_sine_2048,
ff_sine_4096
+ ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024, ff_sine_2048,
ff_sine_4096, ff_sine_8192
};
// Generate a sine window.
diff --git a/libavcodec/wma.c b/libavcodec/wma.c
index 4eaf6fc..8c1186c 100644
--- a/libavcodec/wma.c
+++ b/libavcodec/wma.c
@@ -74,8 +74,9 @@ static void init_coef_vlc(VLC *vlc, uint16_t **prun_table,
*@param decode_flags codec compression features
*@return log2 of the number of output samples per frame
*/
-int av_cold ff_wma_get_frame_len_bits(int sample_rate, int version,
- unsigned int decode_flags)
+int av_cold ff_wma_get_frame_len_bits(AVCodecContext *avctx,
+ int sample_rate, int version,
+ unsigned int decode_flags, int max)
{
int frame_len_bits;
@@ -104,6 +105,11 @@ int av_cold ff_wma_get_frame_len_bits(int sample_rate, int
version,
}
}
+ if (frame_len_bits > max) {
+ av_log_missing_feature(avctx, "High frame len bits", 1);
+ return AVERROR_INVALIDDATA;
+ }
+
return frame_len_bits;
}
@@ -136,7 +142,9 @@ int ff_wma_init(AVCodecContext *avctx, int flags2)
}
/* compute MDCT block size */
- s->frame_len_bits = ff_wma_get_frame_len_bits(s->sample_rate, s->version,
0);
+ s->frame_len_bits = ff_wma_get_frame_len_bits(avctx,
+ s->sample_rate, s->version,
+ 0, BLOCK_MAX_BITS);
s->next_block_len_bits = s->frame_len_bits;
s->prev_block_len_bits = s->frame_len_bits;
s->block_len_bits = s->frame_len_bits;
diff --git a/libavcodec/wma.h b/libavcodec/wma.h
index 4acbf04..8d6452a 100644
--- a/libavcodec/wma.h
+++ b/libavcodec/wma.h
@@ -150,8 +150,9 @@ extern const float ff_wma_lsp_codebook[NB_LSP_COEFS][16];
extern const uint32_t ff_aac_scalefactor_code[121];
extern const uint8_t ff_aac_scalefactor_bits[121];
-int av_cold ff_wma_get_frame_len_bits(int sample_rate, int version,
- unsigned int decode_flags);
+int av_cold ff_wma_get_frame_len_bits(AVCodecContext *avctx,
+ int sample_rate, int version,
+ unsigned int decode_flags, int max);
int ff_wma_init(AVCodecContext * avctx, int flags2);
int ff_wma_total_gain_to_bits(int total_gain);
int ff_wma_end(AVCodecContext *avctx);
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index a1b82db..15162a1 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -105,7 +105,7 @@
#define MAX_FRAMESIZE 32768 ///< maximum
compressed frame size
#define WMAPRO_BLOCK_MIN_BITS 6
///< log2 of min block size
-#define WMAPRO_BLOCK_MAX_BITS 12
///< log2 of max block size
+#define WMAPRO_BLOCK_MAX_BITS 13
///< log2 of max block size
#define WMAPRO_BLOCK_MAX_SIZE (1 << WMAPRO_BLOCK_MAX_BITS)
///< maximum block size
#define WMAPRO_BLOCK_SIZES (WMAPRO_BLOCK_MAX_BITS - WMAPRO_BLOCK_MIN_BITS +
1) ///< possible block sizes
@@ -276,7 +276,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
WMAProDecodeCtx *s = avctx->priv_data;
uint8_t *edata_ptr = avctx->extradata;
unsigned int channel_mask;
- int i;
+ int i, bits;
int log2_max_num_subframes;
int num_possible_block_sizes;
@@ -310,8 +310,12 @@ static av_cold int decode_init(AVCodecContext *avctx)
s->len_prefix = (s->decode_flags & 0x40);
/** get frame len */
- s->samples_per_frame = 1 << ff_wma_get_frame_len_bits(avctx->sample_rate,
- 3, s->decode_flags);
+ bits = ff_wma_get_frame_len_bits(s->avctx, avctx->sample_rate,
+ 3, s->decode_flags,
+ WMAPRO_BLOCK_MAX_BITS);
+ if (bits < 0)
+ return bits;
+ s->samples_per_frame = 1 << bits;
/** subframe info */
log2_max_num_subframes = ((s->decode_flags & 0x38) >> 3);
--
1.7.7.4
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel