shithub: opusfile

Download patch

ref: 34f945bb63b33e5b4069d99ea98b124c4cdde53d
parent: d2577d7fdfda04bc32a853e80e62d6faa2a20859
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Mon Nov 5 06:01:22 EST 2018

Fix SEEK_END usage in seek implementations.

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.

--- a/src/http.c
+++ b/src/http.c
@@ -3151,8 +3151,10 @@
     }break;
     case SEEK_END:{
       /*Check for overflow:*/
-      if(_offset>content_length||_offset<content_length-OP_INT64_MAX)return -1;
-      pos=content_length-_offset;
+      if(_offset<-content_length||_offset>OP_INT64_MAX-content_length){
+        return -1;
+      }
+      pos=content_length+_offset;
     }break;
     default:return -1;
   }
--- a/src/stream.c
+++ b/src/stream.c
@@ -72,7 +72,7 @@
      other libraries (that don't use MSVCRT80 from MSVC 2005 by default).
     i686-w64-mingw32 does have fseeko() and respects _FILE_OFFSET_BITS, but I
      don't know how to detect that at compile time.
-    We could just use fseeko64() (which is available in both), but its
+    We could just use fseeko64() (which is available in both), but it's
      implemented using fgetpos()/fsetpos() just like this code, except without
      the overflow checking, so we prefer our version.*/
   opus_int64 pos;
@@ -322,8 +322,8 @@
       size=stream->size;
       OP_ASSERT(size>=0);
       /*Check for overflow:*/
-      if(_offset>size||_offset<size-OP_MEM_DIFF_MAX)return -1;
-      pos=(ptrdiff_t)(size-_offset);
+      if(_offset<-size||_offset>OP_MEM_DIFF_MAX-size)return -1;
+      pos=(ptrdiff_t)(size+_offset);
     }break;
     default:return -1;
   }