Do proper bounds checking in formats (bug #1356)
[asterisk/asterisk.git] / formats / format_gsm.c
index 078d79d..d58039e 100755 (executable)
@@ -17,6 +17,7 @@
 #include <asterisk/logger.h>
 #include <asterisk/sched.h>
 #include <asterisk/module.h>
+#include <netinet/in.h>
 #include <arpa/inet.h>
 #include <stdlib.h>
 #include <sys/time.h>
 #endif
 #include "msgsm.h"
 
-
-/* Some Ideas for this code came from makegsme.c by Jeffery Chilton */
+/* Some Ideas for this code came from makegsme.c by Jeffrey Chilton */
 
 /* Portions of the conversion code are by guido@sienanet.it */
 
+/* silent gsm frame */
+/* begin binary data: */
+char gsm_silence[] = /* 33 */
+{0xD8,0x20,0xA2,0xE1,0x5A,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49
+,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24
+,0x92,0x49,0x24};
+/* end binary data. size = 33 bytes */
+
 struct ast_filestream {
        void *reserved[AST_RESERVED_POINTERS];
        /* Believe it or not, we must decode/recode to account for the
@@ -185,12 +193,21 @@ static int gsm_seek(struct ast_filestream *fs, long sample_offset, int whence)
        distance = (sample_offset/160) * 33;
        if(whence == SEEK_SET)
                offset = distance;
-       if(whence == SEEK_CUR)
+       else if(whence == SEEK_CUR || whence == SEEK_FORCECUR)
                offset = distance + cur;
-       if(whence == SEEK_END)
+       else if(whence == SEEK_END)
                offset = max - distance;
-       offset = (offset > max)?max:offset;
+       // Always protect against seeking past the begining.
        offset = (offset < min)?min:offset;
+       if (whence != SEEK_FORCECUR) {
+               offset = (offset > max)?max:offset;
+       } else if (offset > max) {
+               int i;
+               lseek(fs->fd, 0, SEEK_END);
+               for (i=0; i< (offset - max) / 33; i++) {
+                       write(fs->fd, gsm_silence, 33);
+               }
+       }
        return lseek(fs->fd, offset, SEEK_SET);
 }