]> git.sesse.net Git - ffmpeg/commitdiff
vorbis: Validate that the floor 1 X values contain no duplicates.
authorAlex Converse <alex.converse@gmail.com>
Tue, 5 Jun 2012 01:27:03 +0000 (18:27 -0700)
committerAlex Converse <alex.converse@gmail.com>
Tue, 5 Jun 2012 16:51:51 +0000 (09:51 -0700)
Duplicate values in this vector are explicitly banned by the Vorbis I spec
and cause divide-by-zero crashes later on.

libavcodec/vorbis.c
libavcodec/vorbis.h
libavcodec/vorbisdec.c
libavcodec/vorbisenc.c

index 52ded8b0a8960bc67d6080dbe90c23033e33a208..16fb998fabc0c2b77ab74cce1be06e5d7508e87a 100644 (file)
@@ -119,7 +119,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;
@@ -143,6 +144,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;
@@ -150,6 +156,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,
index 924ca800b2526d51623dbe1b8aee1889aab8eec6..ee4967cdfeca9a6a416637c5ce8567daa6ed0ebe 100644 (file)
@@ -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,
index 36db356f27b547031c778126c97437766fa68f0e..3489b8f029e3dc1a3c9ede7032d33a15d38adf31 100644 (file)
@@ -574,7 +574,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;
 
index 0b0caccb7cb28ef59100eb781ae2405647855ebc..173619ae4b7c8fc78f464cbbbe4ed27cf53d411b 100644 (file)
@@ -340,7 +340,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_BUG;
 
     venc->nresidues = 1;
     venc->residues  = av_malloc(sizeof(vorbis_enc_residue) * venc->nresidues);