Additional fix to last-page handling, this time in initial bisection;
[platform/upstream/libvorbis.git] / lib / codebook.c
index 6be63dc..db0066c 100644 (file)
@@ -53,8 +53,8 @@ int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){
     oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */
 
     for(i=1;i<c->entries;i++){
-      long this=c->lengthlist[i];
-      long last=c->lengthlist[i-1];
+      char this=c->lengthlist[i];
+      char last=c->lengthlist[i-1];
       if(this>last){
         for(j=last;j<this;j++){
           oggpack_write(opb,i-count,_ilog(c->entries-count));
@@ -163,12 +163,17 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
 
   /* codeword ordering.... length ordered or unordered? */
   switch((int)oggpack_read(opb,1)){
-  case 0:
+  case 0:{
+    long unused;
+    /* allocated but unused entries? */
+    unused=oggpack_read(opb,1);
+    if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
+      goto _eofout;
     /* unordered */
     s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
 
     /* allocated but unused entries? */
-    if(oggpack_read(opb,1)){
+    if(unused){
       /* yes, unused entries */
 
       for(i=0;i<s->entries;i++){
@@ -189,17 +194,23 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
     }
 
     break;
+  }
   case 1:
     /* ordered */
     {
       long length=oggpack_read(opb,5)+1;
+      if(length==0)goto _eofout;
       s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
 
       for(i=0;i<s->entries;){
         long num=oggpack_read(opb,_ilog(s->entries-i));
         if(num==-1)goto _eofout;
+        if(length>32 || num>s->entries-i ||
+           (num>0 && (num-1)>>(length-1)>1)){
+          goto _errout;
+        }
         if(length>32)goto _errout;
-        for(j=0;j<num && i<s->entries;j++,i++)
+        for(j=0;j<num;j++,i++)
           s->lengthlist[i]=length;
         length++;
       }
@@ -237,6 +248,8 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
       }
 
       /* quantized values */
+      if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb))
+        goto _eofout;
       s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals);
       for(i=0;i<quantvals;i++)
         s->quantlist[i]=oggpack_read(opb,s->q_quant);
@@ -354,6 +367,7 @@ long vorbis_book_decode(codebook *book, oggpack_buffer *b){
 }
 
 /* returns 0 on OK or -1 on eof *************************************/
+/* decode vector / dim granularity gaurding is done in the upper layer */
 long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
   if(book->used_entries>0){
     int step=n/book->dim;
@@ -373,6 +387,7 @@ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
   return(0);
 }
 
+/* decode vector / dim granularity gaurding is done in the upper layer */
 long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
   if(book->used_entries>0){
     int i,j,entry;
@@ -418,6 +433,9 @@ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
   return(0);
 }
 
+/* unlike the others, we guard against n not being an integer number
+   of <dim> internally rather than in the upper layer (called only by
+   floor0) */
 long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
   if(book->used_entries>0){
     int i,j,entry;
@@ -427,15 +445,15 @@ long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
       entry = decode_packed_entry_number(book,b);
       if(entry==-1)return(-1);
       t     = book->valuelist+entry*book->dim;
-      for (j=0;j<book->dim;)
+      for (j=0;i<n && j<book->dim;){
         a[i++]=t[j++];
+      }
     }
   }else{
-    int i,j;
+    int i;
 
     for(i=0;i<n;){
-      for (j=0;j<book->dim;)
-        a[i++]=0.f;
+      a[i++]=0.f;
     }
   }
   return(0);