diff options
author | Alex Converse <alex.converse@gmail.com> | 2012-06-04 18:27:03 -0700 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2012-10-06 09:40:46 +0200 |
commit | d6e250abfc36b239ef0c1fc9d45d588b853bfcb9 (patch) | |
tree | 12310ad6c2bf4660839217e39f2bc652bf2f4f1d | |
parent | 61ece41372989cca40634a4f32ff6131d19f99a2 (diff) | |
download | ffmpeg-d6e250abfc36b239ef0c1fc9d45d588b853bfcb9.tar.gz |
vorbis: Validate that the floor 1 X values contain no duplicates.
Duplicate values in this vector are explicitly banned by the Vorbis I spec
and cause divide-by-zero crashes later on.
(cherry picked from commit ecf79c4d3e8baaf2f303278ef81db6f8407656bc)
Signed-off-by: Reinhard Tartler <siretart@tauware.de>
(cherry picked from commit 9aaaeba45c41cf2b3fa4100abbdee7437428f93c)
Signed-off-by: Anton Khirnov <anton@khirnov.net>
-rw-r--r-- | libavcodec/vorbis.c | 9 | ||||
-rw-r--r-- | libavcodec/vorbis.h | 3 | ||||
-rw-r--r-- | libavcodec/vorbisdec.c | 6 | ||||
-rw-r--r-- | libavcodec/vorbisenc.c | 3 |
4 files changed, 17 insertions, 4 deletions
diff --git a/libavcodec/vorbis.c b/libavcodec/vorbis.c index 20be707313..e0eda46f71 100644 --- a/libavcodec/vorbis.c +++ b/libavcodec/vorbis.c @@ -117,7 +117,8 @@ int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) return 0; } -void ff_vorbis_ready_floor1_list(vorbis_floor1_entry * list, int values) +int ff_vorbis_ready_floor1_list(AVCodecContext *avccontext, + vorbis_floor1_entry *list, int values) { int i; list[0].sort = 0; @@ -141,6 +142,11 @@ void ff_vorbis_ready_floor1_list(vorbis_floor1_entry * list, int values) for (i = 0; i < values - 1; i++) { int j; for (j = i + 1; j < values; j++) { + if (list[i].x == list[j].x) { + av_log(avccontext, AV_LOG_ERROR, + "Duplicate value found in floor 1 X coordinates\n"); + return AVERROR_INVALIDDATA; + } if (list[list[i].sort].x > list[list[j].sort].x) { int tmp = list[i].sort; list[i].sort = list[j].sort; @@ -148,6 +154,7 @@ void ff_vorbis_ready_floor1_list(vorbis_floor1_entry * list, int values) } } } + return 0; } static inline void render_line_unrolled(intptr_t x, int y, int x1, diff --git a/libavcodec/vorbis.h b/libavcodec/vorbis.h index 8501e0a178..b4346fbbe7 100644 --- a/libavcodec/vorbis.h +++ b/libavcodec/vorbis.h @@ -36,7 +36,8 @@ typedef struct { uint16_t high; } vorbis_floor1_entry; -void ff_vorbis_ready_floor1_list(vorbis_floor1_entry * list, int values); +int ff_vorbis_ready_floor1_list(AVCodecContext *avccontext, + vorbis_floor1_entry *list, int values); unsigned int ff_vorbis_nth_root(unsigned int x, unsigned int n); // x^(1/n) int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num); void ff_vorbis_floor1_render_list(vorbis_floor1_entry * list, int values, diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index d6850b7f48..3805d27627 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -559,7 +559,11 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) } // Precalculate order of x coordinates - needed for decode - ff_vorbis_ready_floor1_list(floor_setup->data.t1.list, floor_setup->data.t1.x_list_dim); + if (ff_vorbis_ready_floor1_list(vc->avccontext, + floor_setup->data.t1.list, + floor_setup->data.t1.x_list_dim)) { + return AVERROR_INVALIDDATA; + } } else if (floor_setup->floor_type == 0) { unsigned max_codebook_dim = 0; diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c index ad69c61695..7311c05d36 100644 --- a/libavcodec/vorbisenc.c +++ b/libavcodec/vorbisenc.c @@ -336,7 +336,8 @@ static int create_vorbis_context(vorbis_enc_context *venc, }; fc->list[i].x = a[i - 2]; } - ff_vorbis_ready_floor1_list(fc->list, fc->values); + if (ff_vorbis_ready_floor1_list(avccontext, fc->list, fc->values)) + return AVERROR(EINVAL); venc->nresidues = 1; venc->residues = av_malloc(sizeof(vorbis_enc_residue) * venc->nresidues); |