diff options
author | Monty <xiphmont@xiph.org> | 2010-10-14 06:33:23 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2010-10-14 06:33:23 +0000 |
commit | b9c08ec6665166afcfb2b2a99a6bab6d0ae4ec0e (patch) | |
tree | 8b6e5f6a9bd3bf65cf51940b5d053a546907752a /vorbisfile.c | |
parent | fcd8a58ddfcf3d9bfaa15971e244e8ecb623b08b (diff) | |
download | tremor-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
Diffstat (limited to 'vorbisfile.c')
-rw-r--r-- | vorbisfile.c | 35 |
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; } |