Skip to content
Snippets Groups Projects
  1. Sep 15, 2024
    • Martin Guy's avatar
      Fix compilation on AIX 7.3 · 3ecc22aa
      Martin Guy authored and Timothy B. Terriberry's avatar Timothy B. Terriberry committed
      On AIX, compilation fails saying
      
          src/http.c: In function 'op_http_conn_start_tls':
          src/http.c:1944:5: warning: ISO C forbids nested functions [-Wpedantic]
           1944 |     int                ip_len;
      	  |     ^~~
          In file included from /usr/include/netinet/tcp.h:115,
      		     from src/http.c:345:
          src/http.c:1944:24: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token
           1944 |     int                ip_len;
          src/http.c:1944:24: error: expected expression before '.' token
          src/http.c:1949:5: error: 'ip_ff' undeclared (first use in this function); did you mean 'ip_fv'?
           1949 |     ip_len=0;
      
      because `/usr/include/netinet/ip-h` contains
      
          #define  ip_len  ip_ff.ip_flen
      
      The obvious solution os to rename the int variable to something else.
      3ecc22aa
  2. Sep 07, 2022
  3. Dec 16, 2020
    • Timothy B. Terriberry's avatar
      Fix an incorrect assertion in op_pcm_seek_page(). · 729c88e7
      Timothy B. Terriberry authored
      When we were checking the current file offset to see if we should
       use it as the starting bisection point, we assumed that offset was
       larger than the start of the data range for that link (and
       consequently, inside the bisection range).
      If there is a random page earlier in the file that happens to use
       the same serial number as a link we identified later in the file
       at file open time, and we had stopped reading there before the
       seek, then this assumption might not be true.
      
      Ironically, it was not the case that contained the assertion that
       had trouble with such an offset.
      It would fail the check that we were cutting off more than half the
       range, since we were actually cutting off a negative amount, and
       fall back to the midpoint of the link as the first bisection
       point.
      However, the case below that (where the target comes after the
       current timestamp), we might have erroneously cut off the entire
       range (setting end to offset, which was less than begin), causing
       the seek to immediately fail.
      
      Instead, validate the curent offset against both ends of the link
       before attempting to use it as the initial bisection point.
      Thanks to Felicia Lim for the report.
      
      Fixes #2331
      729c88e7
    • Timothy B. Terriberry's avatar
      Fix intermediate overflow in op_pcm_total(). · 82adfb61
      Timothy B. Terriberry authored
      Although link enumeration ensures the return value is in range, the
       order of operations allows the intermediate value pcm_total+diff
       to overflow the range of a 64-bit int.
      Add parentheses to ensure this does not happen.
      Thanks to Felcia Lim for the report.
      
      Fixes #2330
      82adfb61
  4. Oct 13, 2020
    • Timothy B. Terriberry's avatar
      Fix short-circuit test when seeking in short files · 4174c26e
      Timothy B. Terriberry authored
      When a file is very, very short (i.e., only one packet) and uses
       end-trimming, the apparent granule position preceding the first
       sample in the first packet can underflow.
      We were computing this value by subtracting the packet duration
       from the computed per-packet granule position and expecting this
       computation to always succeed.
      Because it could fail in the presence of end-trimming on the first
       packet (ironically, exactly the situation where the short-circuit
       is helpful), it would leave the value uninitialized, and then use
       it in a comparison, which is undefined behavior.
      The correct solution is to check for failure and force the previous
       page's granule position to 0 in this case.
      4174c26e
  5. Sep 16, 2020
    • Timothy B. Terriberry's avatar
      Fix a possible divide-by-zero. · f94a1764
      Timothy B. Terriberry authored
      We were attempting to ensure a minimum spacing between granule
       positions when guessing the start of a link location.
      However, we took a strictly-positive granule position, added a
       fixed increment with op_granpos_add(), and checked if
       op_granpos_add() failed.
      op_granpos_add() only fails if the sum would have overflowed past
       zero, which can never happen when adding two strictly positive
       granule positions.
      Instead, we need to check if the result becomes negative (which is
       a legal granule position, but violates our assumptions in the
       search).
      
      Thanks to Felicia Lim for the report.
      f94a1764
  6. Aug 01, 2020
  7. Jun 26, 2020
  8. Jun 25, 2020
  9. May 02, 2020
    • Timothy B. Terriberry's avatar
      Silence scan-build false positives. · ccdef60e
      Timothy B. Terriberry authored
      The actual guarantees we are making in op_read_native() are:
      - if _pcm == NULL, then _buf_sz <= 0 (requirement on the caller),
      - op_get_packet_duration() will succeed and return a positive value
         no larger than 120*48 (guaranteed by op_collect_audio_packets()
         filtering out any packets with invalid TOC sequences), and
      - nchannels is a small number greater than 0 (guaranteed by the
         validation in opus_parse_head()).
      However, trying to assert these things is not enough to convince
       clang to take the nsamples*nchannels>_buf_sz or
       duration*nchannels>_buf_sz branches when _pcm==NULL, so instead
       we have to be a bit more direct.
      ccdef60e
    • Timothy B. Terriberry's avatar
      Relax some assumptions about our seeking success. · 77121e1b
      Timothy B. Terriberry authored
      There really isn't anything that guarantees we can find timestamps
       within the bounds of the link, or within 2 billion samples of the
       target, if people resort to nasty things like swapping out all of
       the underlying file data on us at the right moment.
      Reported by clang's static analysis in
       https://github.com/xiph/opusfile/issues/16
      
      Thanks to kcgen for filing the report.
      77121e1b
    • Timothy B. Terriberry's avatar
      Avoid a potential divide-by-zero. · a931e217
      Timothy B. Terriberry authored
      Reported by clang's static analysis in
       https://github.com/xiph/opusfile/issues/16
      This would have taken about 22 TB of junk data before the first
       decoded sample to trigger, so not very likely to occur in
       practice.
      
      Thanks to kcgen for filing the report.
      a931e217
  10. Apr 30, 2020
    • Mark Harris's avatar
      Silence clang 10 conversion warning · 8f00bcbf
      Mark Harris authored
       src/opusfile.c:3242:18: warning: implicit conversion from 'unsigned
             int' to 'float' changes value from 4294967295 to 4294967296
             [-Wimplicit-int-float-conversion]
                 r=seed*OP_PRNG_GAIN;
                        ^~~~~~~~~~~~
       src/opusfile.c:3179:29: note: expanded from macro 'OP_PRNG_GAIN'
       # define OP_PRNG_GAIN (1.0F/0xFFFFFFFF)
                                  ~^~~~~~~~~~
      Verified
      8f00bcbf
    • Mark Harris's avatar
      http: Fix use of deprecated function ftime() · 069dc6e8
      Mark Harris authored
      The ftime() function, introduced in V7 Unix (1979), gets the current
      time in seconds and milliseconds, and time zone information.  It was
      marked as a legacy interface in POSIX.1-2001, and removed altogether
      from POSIX.1-2008.  The gettimeofday() function, originally from
      4.1 BSD, gets the current time in seconds and microseconds, and optional
      time zone information, and was marked as obsolete in POSIX.1-2008
      although it was kept in the standard.  The POSIX recommended function
      for getting time with sub-second resolution is clock_gettime(), which
      was introduced in POSIX.1b-1993 and is now part of the base POSIX
      standard; it supports multiple clocks and nanosecond resolution.
      Additionally the function timespec_get() was introduced in C11 and also
      supports nanosecond resolution.
      
      To support dates beyond the year 2038, glibc and other libraries are
      being updated to support 64-bit time_t even on 32-bit architectures,
      requiring new implementations of interfaces that work with time.  As
      part of this effort, the ftime() function was deprecated in glibc 2.31
      (released February 1, 2020), a warning is now issued when building code
      that uses this function, and removal is planned for a future version of
      glibc (https://sourceware.org/pipermail/libc-announce/2020/000025.html).
      
      ftime() is used in http.c to measure time intervals with millisecond
      resolution.  To avoid the glibc 2.31 deprecation warning and further
      issues when the function is removed entirely from glibc, clock_gettime()
      is now used instead when it is available in the C library, as it is on
      current Linux systems.  Prior to glibc 2.17, clock_gettime() required
      linking with librt; on such systems ftime() will continue to be used, to
      avoid an additional library dependency.  macOS provides clock_gettime()
      starting in macOS 10.12; earlier versions will continue to use ftime().
      Windows provides ftime() but not clock_gettime(), so ftime() will
      continue to be used on Windows.
      
      ftime(), gettimeofday(), and clock_gettime() with the CLOCK_REALTIME
      clock get the "real time", which is subject to jumps if set by an
      administrator or time service.  The CLOCK_MONOTONIC clock does not have
      this problem and is more suitable for measuring time intervals.  On
      Linux, the CLOCK_BOOTTIME clock measures the time since last boot and is
      the same as CLOCK_MONOTONIC except that the Linux CLOCK_MONOTONIC clock
      does not advance when the system is suspended.  Because it is used to
      measure time intervals, CLOCK_BOOTTIME or CLOCK_MONOTONIC are used when
      available, when clock_gettime() is used.  However the only clock
      required by POSIX.1-2008 is CLOCK_REALTIME, so that will be used if the
      other clocks are not available.
      Verified
      069dc6e8
  11. Apr 24, 2020
    • Timothy B. Terriberry's avatar
      Fix handling of holes again. · 85f7aa22
      Timothy B. Terriberry authored
      It is possible for us to buffer multiple out-of-sequence pages with no packets
       on them before getting one that does have packets.
      In this case, libogg will report each hole in the page sequence numbers
       separately.
      Since we were only checking for the actual packets once after encountering a
       hole, if the total number of holes was even, we could exit
       op_fetch_and_process_page() with valid packets still in the libogg buffer.
      Then, if the next page had a lot of packets, we might wind up with a total of
       more than 255 of them, overflowing our stack buffer for their durations.
      That's bad.
      
      Instead, make sure we always drain all hole reports from libogg any time we
       encounter one, to ensure we get the actual packets behind it.
      
      Thanks to Felicia Lim for the report.
      85f7aa22
  12. Nov 22, 2019
  13. Dec 10, 2018
    • Timothy B. Terriberry's avatar
      Fix to avoid technically undefined behavior. · 1bd200bc
      Timothy B. Terriberry authored
      The C standard says that calling library functions (including
       memcpy) with invalid arguments (including a NULL pointer) is
       undefined behavior unless otherwise noted (which memcpy doesn't).
      op_filter_read_native() invokes op_read_native() with NULL for the
       _pcm buffer, which triggers such a memcpy invocation.
      Even though it should be perfectly fine in practice to pass NULL to
       memcpy when copying zero bytes, don't do it.
      
      Thanks to a person who did not wish to be credited for the report.
      1bd200bc
    • Timothy B. Terriberry's avatar
      Fix seekability detection on win32. · 24cb5eae
      Timothy B. Terriberry authored
      The seeking functions on Windows internally dispatch to
       SetFilePointer(), whose behavior is undefined if you do not call
       it on "a file stored on a seeking device".
      Check the type of file when it is opened and manually force seeks
       to fail if we do not have such a file.
      
      Thanks to L W Anhonen for the report and Mark Harris for pointing
       out the solution used by opus-tools to avoid this problem.
      24cb5eae
  14. Nov 06, 2018
    • Timothy B. Terriberry's avatar
      Fix SEEK_END usage in seek implementations. · 34f945bb
      Timothy B. Terriberry authored
      When seeking using SEEK_END, the win32-specific implementation of
       op_fseek() would add the offset to the file size to get the
       absolute seek position.
      However, op_mem_seek() and op_http_stream_seek() would subtract the
       offset instead.
      The documentation of fseek() is not at all clear which behavior is
       correct, but I believe that the op_fseek() behavior is.
      
      This inconsistency didn't matter for opusfile in practice, because
       we only ever use SEEK_END with an offset of 0.
      However, the user can also open files with our API and use the
       resulting callbacks for their own purposes, so it would be good to
       be consistent for them.
      
      Thanks to a person who did not wish to be credited for the report.
      34f945bb
  15. Nov 01, 2018
    • Stefan Strogin's avatar
      http: use new API with LibreSSL >=2.7.0 · d2577d7f
      Stefan Strogin authored and Ralph Giles's avatar Ralph Giles committed
      
      LibreSSL is not yet fully API compatible with OpenSSL 1.0.2 and later,
      However many APIs from OpenSSL 1.0.2 and 1.1 are already implemented in
      LibreSSL 2.7.0 and later. Old approach works in newer LibreSSL version
      as well, but it's not nice to force deprecated functions on LibreSSL
      users.
      
      Add additional conditionals for new LibreSSL versions to use the
      available new APIs.
      
      Signed-off-by: default avatarRalph Giles <giles@thaumas.net>
      Verified
      d2577d7f
  16. Oct 01, 2018
  17. Jun 12, 2018
  18. Dec 29, 2017
  19. Dec 07, 2017
  20. Sep 12, 2017
  21. Aug 02, 2017
    • Timothy B. Terriberry's avatar
      Minor win32 warning fix. · dc27cf17
      Timothy B. Terriberry authored
      op_fopen() and op_freopen() declare these arguments as non-NULL,
       so when building with mingw, the compiler reasonably complains
       when we check to see if they're NULL.
      We could remove the OP_ARG_NONNULL tags, but the behavior of
       _wopen/_wfreopen appears to be to crash on NULL for either
       parameter.
      On Linux, the behavior appears to be to handle a NULL path (fopen
       returns NULL with errno set to EFAULT, and freopen returns the
       passed FILE * with errno set to EFAULT), but crash on a NULL mode.
      Keeping the OP_ARG_NONNULL tags promises that passing NULL results
       in undefined behavior, which is at least consistent with the
       behavior being different on different platforms.
      It's also consistent with the ABI promises of previous releases,
       which compilers linking against libopusfile might have taken
       advantage of.
      dc27cf17
  22. Jul 07, 2017
    • Timothy B. Terriberry's avatar
      Improve source/stream terminology consistency · c59d42b6
      Timothy B. Terriberry authored
      We inherited the term "source" from vorbisfile's "datasource", but
       were using it interchangeably with stream.
      At least one user did not even realize the that the _source
       parameter passed to op_open_callbacks() was the same as the
       _stream parameter taken by those callbacks, which is reasonable
       because we never said so.
      Consistently use "stream" instead of "source" in both the
       documentation and the code.
      c59d42b6
  23. Jun 17, 2017
  24. May 24, 2017
    • Timothy B. Terriberry's avatar
      Fix two compiler warnings. · 3b3b3e55
      Timothy B. Terriberry authored
      Thanks to Mark Harris for the report.
      3b3b3e55
    • Timothy B. Terriberry's avatar
      Fix uninitialized free in tag parsing. · 529bd012
      Timothy B. Terriberry authored
      The tags have two possible representations of the binary suffix
       data.
      An implicit one: if comment_lengths and user_comments are NULL,
       then the length of the binary suffix data is 0 and the pointer to
       that data is also implicitly taken to be NULL.
      And an explicit one: if comment_lengths and user_comments are
       non-NULL, then comment_lengths[comments] and
       user_comments[comments] contains the length and pointer to the
       binary suffix data (where "comments" is the number of user
       comments).
      
      The implicit one allows us to initialize a tags struct without
       doing any allocations, which ensures it always succeeds.
      op_tags_ensure_capacity() may upgrade the implicit representation
       to the explicit representation.
      However, when doing so, it stores the implicit (0, NULL) values
       in their new explicit locations at the end of the array assuming
       the requested capacity will become the new size.
      If the caller of op_tags_ensure_capacity() then fails before
       enlarging the array to that size, then comment_lengths and
       user_comments will be non-NULL, but the explicit locations for the
       binary suffix data for the _old_ size may not have been
       initialized.
      
      In particular, in opus_tags_parse_impl(), if there was exactly one
       comment, and any of the three checks at the start of the main loop
       failed, then the explicit locations for the binary suffix data
       would remain uninitialized, and the call to opus_tags_clear() in
       the caller would attempt to free them.
      For counts larger than 1, the extra line marked "Needed by
       opus_tags_clear()" will update the explicit location as the array
       grows, but with a count of 1 this line never gets a chance to run.
      
      This patch fixes the problem by making op_tags_ensure_capacity()
       promote the implicit representation to explicit at _both_ the old
       and new array sizes.
      We could have fixed up opus_tags_parse_impl() to do this instead,
       as suggested in the original bug reports, but doing it this way
       ensures that the tags are always in a valid state when
       op_tags_ensure_capacity() returns.
      
      Thanks to the Google AutoFuzz Team for the report.
      
      Fixes #2324
      Fixes #2325
      529bd012
  25. May 19, 2017
    • Timothy B. Terriberry's avatar
      Harmonize op_raw_total() and op_raw_seek() · 37f83754
      Timothy B. Terriberry authored
      op_raw_seek() will fail if you try to seek to a byte position
       beyond the end of the file.
      However, the "end" is defined in terms of _of->end, which is
       specifically the end of the last Ogg page found in the underlying
       source (excluding any trailing non-Ogg data).
      op_raw_total(_of,-1) returns the total size of the stream by using
       _of->end, but it was also subtracting the offset of the first Opus
       page in the first link.
      Since there might have been other Ogg streams concurrently
       multiplexed with the first Opus stream whose BOS pages appear
       first, or there might simply be non-Ogg junk at the start, that
       left the caller with no way to determine the valid range of byte
       offsets that could be passed to op_raw_seek().
      
      Instead, make op_raw_total() pretend the first link starts at
       offset 0, and explicitly document that it's what defines the range
       of valid values to op_raw_seek().
      This is how our own seeking_example.c was using it, anyway.
      37f83754
    • Timothy B. Terriberry's avatar
      Improve handling of holes (corrupt pages). · fd65b94f
      Timothy B. Terriberry authored
      Previously, when we encountered a hole (a gap in the page sequence
       numbers), we would save off all of the packets from the first page
       after the hole, but not timestamp them.
      That meant when they were actually decoded, op_pcm_tell() would
       report a timestamp of 0 until reaching the last packet on that
       page.
      
      Instead, handle holes just like a raw seek.
      We reset the granule position tracking, and attempt to timestamp
       packets backwards from the end of the page.
      If the first page after the hole is an EOS page, we just throw it
       away (rather than risk playing invalid samples due to incorrect
       end-trimming).
      We also throw away the first 80 ms of audio after a hole, to allow
       the decoder state to reconverge.
      
      This patch also updates the example to report the hole and
       continue decoding, rather than immediately stopping when a hole is
       encountered, in order to test the above features.
      fd65b94f
    • Timothy B. Terriberry's avatar
      Avoid operations linear in the number of links. · f83675eb
      Timothy B. Terriberry authored
      Just in case some bozo makes a chained stream with 272,389 links
       with 16 samples in each (coded at 16 Mbps, including overheads).
      This avoids quadratic behavior for simple straight-through
       playback: we no longer do a linear search on each chain boundary
       or each call to op_pcm_tell().
      N seeks with M chains still requires O(N*log(M)) work.
      f83675eb
    • Timothy B. Terriberry's avatar
      Minor comment updates. · 21ebba38
      Timothy B. Terriberry authored
      No code changes.
      21ebba38
    • Timothy B. Terriberry's avatar
      Use OpenSSL's hostname validation if available. · cc1fff58
      Timothy B. Terriberry authored
      As of version 1.0.2, OpenSSL can finally do automatic hostname
       validation for us.
      Their implementation is likely to have received much better review
       than ours, and there are other good reasons to prefer it, so use it
       when we can.
      cc1fff58
Loading