diff --git a/config.cmake.h.in b/config.cmake.h.in index 1aeaffc804..7fca78e2ef 100644 --- a/config.cmake.h.in +++ b/config.cmake.h.in @@ -109,6 +109,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STAT_H +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TYPES_H diff --git a/configure.ac b/configure.ac index 6391501bdb..f1f05c5fd8 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ AM_PROG_CC_C_O AC_C_INLINE AC_C_TYPEOF -AC_CHECK_HEADERS([stdint.h stdbool.h inttypes.h byteswap.h sys/auxv.h sys/param.h sys/ioctl.h termios.h x86intrin.h cpuid.h arm_neon.h]) +AC_CHECK_HEADERS([stdint.h stdbool.h inttypes.h byteswap.h sys/auxv.h sys/param.h sys/ioctl.h sys/time.h termios.h x86intrin.h cpuid.h arm_neon.h]) if test "x$ac_cv_header_stdint_h" != xyes -o "x$ac_cv_header_stdbool_h" != xyes; then AC_MSG_ERROR("Header stdint.h and/or stdbool.h not found") diff --git a/src/flac/CMakeLists.txt b/src/flac/CMakeLists.txt index da7ce8de9c..8b4e52a131 100644 --- a/src/flac/CMakeLists.txt +++ b/src/flac/CMakeLists.txt @@ -1,4 +1,5 @@ check_include_file("sys/ioctl.h" HAVE_SYS_IOCTL_H) +check_include_file("sys/time.h" HAVE_SYS_TIME_H) check_include_file("termios.h" HAVE_TERMIOS_H) add_executable(flacapp diff --git a/src/flac/main.c b/src/flac/main.c index 6087371528..dc8c23cb06 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -30,6 +30,10 @@ #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif + #if !defined _MSC_VER && !defined __MINGW32__ /* unlink is in stdio.h in VC++ */ #include /* for unlink() */ @@ -322,7 +326,30 @@ static int main_to_fuzz(int argc, char *argv[]) _setmode(fileno(stderr),_O_U8TEXT); #endif - srand((uint32_t)time(0)); +#ifdef HAVE_SYS_TIME_H + { + struct timeval tv; + + if (gettimeofday(&tv, 0) < 0) { + srand(((uint32_t)time(0) << 8) + (uint32_t)clock()); + } + else { + /* fall back when gettimeofday fails */ + srand((uint32_t)(tv.tv_sec) * 1e6 + (uint32_t)tv.tv_usec); + } + } +#else + /* time(0) does not have sufficient resolution when flac is invoked more than + * once in quick succession (for example in the test suite). As far as I know, + * clock() is the only sub-second portable alternative, but measures + * execution time, which is often quite similar between runs. From limited + * testing, it seems the value varies by about 100, so that would make + * collision 100 times less likely than without. Therefore, use + * both together to generate a random number seed. + */ + srand(((uint32_t)time(0) << 8) + (uint32_t)clock()); +#endif + #ifdef _WIN32 { const char *var; @@ -1640,7 +1667,10 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ encode_options.use_ogg = option_values.use_ogg; /* set a random serial number if one has not yet been specified */ if(!option_values.has_serial_number) { - option_values.serial_number = rand(); + if (RAND_MAX < 0x7fffffff) + option_values.serial_number = (uint32_t)(rand() & 0x7fff) << 16 | (uint32_t)(rand()); + else + option_values.serial_number = rand(); option_values.has_serial_number = true; } encode_options.serial_number = option_values.serial_number++;