Fix signed overflow in _book_maptype1_quantvals().
authorTimothy B. Terriberry <tterribe@xiph.org>
Tue, 4 Oct 2016 01:22:16 +0000 (18:22 -0700)
committerRalph Giles <giles@mozilla.com>
Fri, 16 Jun 2017 18:40:19 +0000 (11:40 -0700)
If b->dims is very large, vals will be 1 and acc1 will overflow a
 long.
This causes us to read too many values for this codebook.

Signed-off-by: Monty <xiphmont@xiph.org>
lib/sharedbook.c

index 0326def..f8854f7 100644 (file)
@@ -16,6 +16,7 @@
  ********************************************************************/
 
 #include <stdlib.h>
+#include <limits.h>
 #include <math.h>
 #include <string.h>
 #include <ogg/ogg.h>
@@ -158,25 +159,34 @@ ogg_uint32_t *_make_words(char *l,long n,long sparsecount){
    that's portable and totally safe against roundoff, but I haven't
    thought of it.  Therefore, we opt on the side of caution */
 long _book_maptype1_quantvals(const static_codebook *b){
-  long vals=floor(pow((float)b->entries,1.f/b->dim));
+  long vals;
+  if(b->entries<1){
+    return(0);
+  }
+  vals=floor(pow((float)b->entries,1.f/b->dim));
 
   /* the above *should* be reliable, but we'll not assume that FP is
      ever reliable when bitstream sync is at stake; verify via integer
      means that vals really is the greatest value of dim for which
      vals^b->bim <= b->entries */
   /* treat the above as an initial guess */
+  if(vals<1){
+    vals=1;
+  }
   while(1){
     long acc=1;
     long acc1=1;
     int i;
     for(i=0;i<b->dim;i++){
+      if(b->entries/vals<acc)break;
       acc*=vals;
-      acc1*=vals+1;
+      if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX;
+      else acc1*=vals+1;
     }
-    if(acc<=b->entries && acc1>b->entries){
+    if(i>=b->dim && acc<=b->entries && acc1>b->entries){
       return(vals);
     }else{
-      if(acc>b->entries){
+      if(i<b->dim || acc>b->entries){
         vals--;
       }else{
         vals++;