Do proper bounds checking in formats (bug #1356)
[asterisk/asterisk.git] / formats / format_wav_gsm.c
index fc8364c..6c988bd 100755 (executable)
 #endif
 #include "msgsm.h"
 
 #endif
 #include "msgsm.h"
 
-/* Some Ideas for this code came from makewave.c by Jeffery Chilton */
+/* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
 
 /* Portions of the conversion code are by guido@sienanet.it */
 
 
 /* Portions of the conversion code are by guido@sienanet.it */
 
+/* begin binary data: */
+char msgsm_silence[] = /* 65 */
+{0x48,0x17,0xD6,0x84,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49
+,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92
+,0x24,0x09,0x82,0x74,0x61,0x4D,0x28,0x00,0x48,0x92,0x24,0x49,0x92,0x28,0x00
+,0x48,0x92,0x24,0x49,0x92,0x28,0x00,0x48,0x92,0x24,0x49,0x92,0x28,0x00,0x48
+,0x92,0x24,0x49,0x92,0x00};
+/* end binary data. size = 65 bytes */
+
 struct ast_filestream {
        void *reserved[AST_RESERVED_POINTERS];
        /* Believe it or not, we must decode/recode to account for the
 struct ast_filestream {
        void *reserved[AST_RESERVED_POINTERS];
        /* Believe it or not, we must decode/recode to account for the
@@ -59,7 +68,7 @@ static int glistcnt = 0;
 
 static char *name = "wav49";
 static char *desc = "Microsoft WAV format (Proprietary GSM)";
 
 static char *name = "wav49";
 static char *desc = "Microsoft WAV format (Proprietary GSM)";
-static char *exts = "WAV";
+static char *exts = "WAV|wav49";
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define htoll(b) (b)
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define htoll(b) (b)
@@ -209,7 +218,8 @@ static int update_header(int fd)
        
        cur = lseek(fd, 0, SEEK_CUR);
        end = lseek(fd, 0, SEEK_END);
        
        cur = lseek(fd, 0, SEEK_CUR);
        end = lseek(fd, 0, SEEK_END);
-       bytes = end - 52;
+       /* in a gsm WAV, data starts 60 bytes in */
+       bytes = end - 60;
        datalen = htoll(bytes);
        filelen = htoll(52 + ((bytes + 1) & ~0x1));
        if (cur < 0) {
        datalen = htoll(bytes);
        filelen = htoll(52 + ((bytes + 1) & ~0x1));
        if (cur < 0) {
@@ -471,7 +481,7 @@ static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
 static int wav_seek(struct ast_filestream *fs, long sample_offset, int whence)
 {
        off_t offset=0,distance,cur,min,max;
 static int wav_seek(struct ast_filestream *fs, long sample_offset, int whence)
 {
        off_t offset=0,distance,cur,min,max;
-       min = 52;
+       min = 60;
        cur = lseek(fs->fd, 0, SEEK_CUR);
        max = lseek(fs->fd, 0, SEEK_END);
        /* I'm getting sloppy here, I'm only going to go to even splits of the 2
        cur = lseek(fs->fd, 0, SEEK_CUR);
        max = lseek(fs->fd, 0, SEEK_END);
        /* I'm getting sloppy here, I'm only going to go to even splits of the 2
@@ -483,9 +493,16 @@ static int wav_seek(struct ast_filestream *fs, long sample_offset, int whence)
                offset = distance + cur;
        else if(whence == SEEK_END)
                offset = max - distance;
                offset = distance + cur;
        else if(whence == SEEK_END)
                offset = max - distance;
+       // always protect against seeking past end of header
+       offset = (offset < min)?min:offset;
        if (whence != SEEK_FORCECUR) {
        if (whence != SEEK_FORCECUR) {
-               offset = (offset < min)?min:offset;
                offset = (offset > max)?max:offset;
                offset = (offset > max)?max:offset;
+       } else if (offset > max) {
+               int i;
+               lseek(fs->fd, 0, SEEK_END);
+               for (i=0; i< (offset - max) / 65; i++) {
+                       write(fs->fd, msgsm_silence, 65);
+               }
        }
        fs->secondhalf = 0;
        return lseek(fs->fd, offset, SEEK_SET);
        }
        fs->secondhalf = 0;
        return lseek(fs->fd, offset, SEEK_SET);