shithub: sox

Download patch

ref: 6918be14d1e6822a592ec4ad12dccb4c98388d60
parent: dee63f713a6c9ae5d37671ee7ff20b52d50f9232
author: cbagwell <cbagwell>
date: Sun Feb 19 20:33:24 EST 2006

Overflow fixes in aiff and sphere.

--- a/Changelog
+++ b/Changelog
@@ -17,6 +17,9 @@
   o Output filenames with multiple '.' confused SoX.  (Christian Hammers)
   o Moved to a common set of CLIP routines.  This fixed clipping
     bugs in noisered and mcompand.
+  o Stop SoX from crashing on sphere files that contain large text
+    strings.  Ulf Hamhammar
+  o Fix some overflow crashes in aiff handler.  Ulf Hamhammar.
 
 sox-12.17.9
 -----------
--- a/TODO
+++ b/TODO
@@ -100,8 +100,6 @@
 
   o Make a global version of MIN/MAX instead of sprinkled min/max/MIN/MAX
 
-  o Make a global version of clip() instead of sprinked in all files.
-
   o Fix conversions to and from st_sample_t to floats.  Currently,
     its an approximation because it doesn't account from negative
     side having 1 more value then positive side.  That means instead
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -228,19 +228,40 @@
                         else
                             foundmark = 1;
 
-                        chunksize -= 2;
-                        for(i = 0; i < nmarks; i++) {
-                                unsigned char len;
+                        /* Make sure its not larger then we support */
+                        if (nmarks > 32)
+                            nmarks = 32;
 
+                        if (chunksize > 2)
+                            chunksize -= 2;
+                        for(i = 0; i < nmarks && chunksize; i++) {
+                                unsigned char len, read_len, tmp_c;
+
+                                if (chunksize < 6)
+                                    break;
                                 st_readw(ft, &(marks[i].id));
                                 st_readdw(ft, &(marks[i].position));
                                 chunksize -= 6;
-                                st_readb(ft, &len);
-                                chunksize -= len + 1;
-                                for(j = 0; j < len ; j++) 
-                                    st_readb(ft, (unsigned char *)&(marks[i].name[j]));
-                                marks[i].name[j] = 0;
-                                if ((len & 1) == 0) {
+                                /* If error reading length then
+                                 * don't try to read more bytes
+                                 * based on that value.
+                                 */
+                                if (st_readb(ft, &len) != ST_SUCCESS)
+                                    break;
+                                if (len > chunksize)
+                                    len = chunksize;
+                                read_len = len;
+                                if (read_len > 39)
+                                    read_len = 39;
+                                for(j = 0; j < len && chunksize; j++) 
+                                {
+                                    st_readb(ft, &tmp_c);
+                                    if (j < read_len)
+                                        marks[i].name[j] = tmp_c;
+                                    chunksize--;
+                                }
+                                marks[i].name[read_len] = 0;
+                                if ((len & 1) == 0 && chunksize) {
                                         chunksize--;
                                         st_readb(ft, (unsigned char *)&trash8);
                                 }
--- a/src/sphere.c
+++ b/src/sphere.c
@@ -82,18 +82,18 @@
         {
             if (strncmp(buf, "sample_n_bytes", 14) == 0 && ft->info.size == -1)
             {
-                sscanf(buf, "%s %s %d", fldname, fldtype, &i);
+                sscanf(buf, "%63s %15s %d", fldname, fldtype, &i);
                 ft->info.size = i;
             }
             if (strncmp(buf, "channel_count", 13) == 0 && 
                 ft->info.channels == -1)
             {
-                sscanf(buf, "%s %s %d", fldname, fldtype, &i);
+                sscanf(buf, "%63s %15s %d", fldname, fldtype, &i);
                 ft->info.channels = i;
             }
             if (strncmp(buf, "sample_coding", 13) == 0)
             {
-                sscanf(buf, "%s %s %s", fldname, fldtype, fldsval);
+                sscanf(buf, "%63s %15s %127s", fldname, fldtype, fldsval);
                 /* Only bother looking for ulaw flag.  All others
                  * should be caught below by default PCM check
                  */
@@ -106,12 +106,12 @@
             if (strncmp(buf, "sample_rate ", 12) == 0 &&
                 ft->info.rate == 0)
             {
-                sscanf(buf, "%s %s %ld", fldname, fldtype, &rate);
+                sscanf(buf, "%53s %15s %ld", fldname, fldtype, &rate);
                 ft->info.rate = rate;
             }
             if (strncmp(buf, "sample_byte_format", 18) == 0)
             {
-                sscanf(buf, "%s %s %s", fldname, fldtype, fldsval);
+                sscanf(buf, "%53s %15s %127s", fldname, fldtype, fldsval);
                 if (strncmp(fldsval,"01",2) == 0)
                 {
                     /* Data is in little endian. */