summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2010-10-14 06:33:23 +0000
committerMonty <xiphmont@xiph.org>2010-10-14 06:33:23 +0000
commitb9c08ec6665166afcfb2b2a99a6bab6d0ae4ec0e (patch)
tree8b6e5f6a9bd3bf65cf51940b5d053a546907752a
parentfcd8a58ddfcf3d9bfaa15971e244e8ecb623b08b (diff)
downloadtremor-b9c08ec6665166afcfb2b2a99a6bab6d0ae4ec0e.tar.gz
Commit provisional fix for 64 bit math overflow in libvorbisfile
seeking bisection computation This is the equivalent of the r15921 fix in reference, but doesn't require a double cast (for obvious reasons). The technique is different, the intent is the same (avoid a 64x64= >64 bit overflow) git-svn-id: https://svn.xiph.org/trunk/Tremor@17534 0101bb08-14d6-0310-b084-bc0e0c8e3800
-rw-r--r--vorbisfile.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/vorbisfile.c b/vorbisfile.c
index 7594c85..bc4b153 100644
--- a/vorbisfile.c
+++ b/vorbisfile.c
@@ -1352,6 +1352,36 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
return OV_EBADLINK;
}
+/* rescales the number x from the range of [0,from] to [0,to]
+ x is in the range [0,from]
+ from, to are in the range [1, 1<<62-1] */
+ogg_int64_t rescale64(ogg_int64_t x, ogg_int64_t from, ogg_int64_t to){
+ ogg_int64_t frac=0;
+ ogg_int64_t ret=0;
+ int i;
+ if(x >= from) return to;
+ if(x <= 0) return 0;
+
+ for(i=0;i<64;i++){
+ if(x>=from){
+ frac|=1;
+ x-=from;
+ }
+ x<<=1;
+ frac<<=1;
+ }
+
+ for(i=0;i<64;i++){
+ if(frac & 1){
+ ret+=to;
+ }
+ frac>>=1;
+ ret>>=1;
+ }
+
+ return ret;
+}
+
/* Page granularity seek (faster than sample granularity because we
don't do the last bit of decode to find a specific sample).
@@ -1397,8 +1427,9 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
bisect=begin;
}else{
/* take a (pretty decent) guess. */
- bisect=begin +
- (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
+ bisect=begin + rescale64(target-begintime,
+ endtime-begintime,
+ end-begin) - CHUNKSIZE;
if(bisect<begin+CHUNKSIZE)
bisect=begin;
}