shithub: opus-tools

Download patch

ref: fc569f8b886f6da4ab8f0996d45dfffc4755e162
parent: d71e574b3684091b070c3d53a1e67f9fde976c76
author: Gregory Maxwell <greg@xiph.org>
date: Tue Nov 27 10:03:17 EST 2012

Fix opusenc crash on win32 for large files; Length detection on 32bit.

Opusenc was using ftell() whos return is 32 bits on some systems to get the
 input file size and later code was not dealing well with negative sizes.
This commit changes to use 64-bit returning functions where available and
 sanity checks the detected length then treats any cases where the length
 still ends up negative as streams.

Thanks to win32vb on IRC for the report and reproduction.

--- a/configure.ac
+++ b/configure.ac
@@ -285,6 +285,7 @@
         AC_MSG_RESULT([no]))
 CFLAGS="$saved_CFLAGS $EXTRA_WARNS"
 
+AC_FUNC_FSEEKO
 AC_CHECK_FUNCS([lrintf])
 AC_CHECK_FUNCS([lrint])
 AC_CHECK_FUNCS([fminf])
--- a/src/audio-in.c
+++ b/src/audio-in.c
@@ -32,6 +32,16 @@
 # include <config.h>
 #endif
 
+#if !defined(_LARGEFILE_SOURCE)
+# define _LARGEFILE_SOURCE
+#endif
+#if !defined(_LARGEFILE64_SOURCE)
+# define _LARGEFILE64_SOURCE
+#endif
+#if !defined(_FILE_OFFSET_BITS)
+# define _FILE_OFFSET_BITS 64
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -596,8 +606,21 @@
             }
             else
             {
-                opt->total_samples_per_channel = (ftell(in) - pos)/
-                    (format.channels*samplesize);
+#if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
+                opt->total_samples_per_channel = _ftelli64(in);
+#elif defined HAVE_FSEEKO
+                opt->total_samples_per_channel = ftello(in);
+#else
+                opt->total_samples_per_channel = ftell(in);
+#endif
+                if(opt->total_samples_per_channel>pos)
+                {
+                   opt->total_samples_per_channel = (opt->total_samples_per_channel-pos)/(format.channels*samplesize);
+                }
+                else
+                {
+                   opt->total_samples_per_channel=0;
+                }
                 fseek(in,pos, SEEK_SET);
             }
         }