Skip to content

Commit

Permalink
Reduce chance of ogg serial number collision
Browse files Browse the repository at this point in the history
When two ogg streams were made with two different calls to `flac`
within the same second, their serial numbers would be the same.
This caused problems with seeking in the test suite. While in
theory, libFLAC should be able to seek in a chained stream with
two equal serial numbers without fail, in practice seeking in
chained streams is hard enough. So, this commit makes sure the
chained test files have links with unequal serial numbers.
  • Loading branch information
ktmf01 committed Aug 29, 2024
1 parent c74f38e commit 322e143
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
3 changes: 3 additions & 0 deletions config.cmake.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H

/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H

/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H

Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
1 change: 1 addition & 0 deletions src/flac/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
34 changes: 32 additions & 2 deletions src/flac/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#include <string.h>
#include <time.h>

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

#if !defined _MSC_VER && !defined __MINGW32__
/* unlink is in stdio.h in VC++ */
#include <unistd.h> /* for unlink() */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++;
Expand Down

0 comments on commit 322e143

Please sign in to comment.