The code computes the average of two integers using either division or signed right shift, and then uses the result as the index of an array. If the values being averaged are very large, this can overflow (resulting in the computation of a negative average).
This commit is contained in:
parent
39555fc266
commit
facd3ee689
|
|
@ -82,7 +82,7 @@ public class DbSearcher
|
|||
int l = 0, h = totalIndexBlocks;
|
||||
long sip, eip, dataptr = 0;
|
||||
while ( l <= h ) {
|
||||
int m = (l + h) >> 1;
|
||||
int m = Util.mean(l, h);
|
||||
int p = (int)(firstIndexPtr + m * blen);
|
||||
|
||||
sip = Util.getIntLong(dbBinStr, p);
|
||||
|
|
@ -194,7 +194,7 @@ public class DbSearcher
|
|||
|
||||
int l = 0, h = headerLength, sptr = 0, eptr = 0;
|
||||
while ( l <= h ) {
|
||||
int m = (l + h) >> 1;
|
||||
int m = Util.mean(l, h);
|
||||
|
||||
//perfetc matched, just return it
|
||||
if ( ip == HeaderSip[m] ) {
|
||||
|
|
@ -247,7 +247,7 @@ public class DbSearcher
|
|||
l = 0; h = blockLen / blen;
|
||||
long sip, eip, dataptr = 0;
|
||||
while ( l <= h ) {
|
||||
int m = (l + h) >> 1;
|
||||
int m = Util.mean(l, h);
|
||||
int p = m * blen;
|
||||
sip = Util.getIntLong(iBuffer, p);
|
||||
if ( ip < sip ) {
|
||||
|
|
@ -316,7 +316,7 @@ public class DbSearcher
|
|||
byte[] buffer = new byte[blen];
|
||||
long sip, eip, dataptr = 0;
|
||||
while ( l <= h ) {
|
||||
int m = (l + h) >> 1;
|
||||
int m = Util.mean(l, h);
|
||||
raf.seek(firstIndexPtr + m * blen); //set the file pointer
|
||||
raf.readFully(buffer, 0, buffer.length);
|
||||
sip = Util.getIntLong(buffer, 0);
|
||||
|
|
|
|||
|
|
@ -140,4 +140,19 @@ public class Util
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arithmetic mean of {@code x} and {@code y}, rounded towards
|
||||
* negative infinity. This method is overflow resilient.
|
||||
*
|
||||
* code from guava 14.0
|
||||
* com.google.common.math.IntMath.mean(int x, int y)
|
||||
*
|
||||
*/
|
||||
public static int mean(int x, int y) {
|
||||
// Efficient method for computing the arithmetic mean.
|
||||
// The alternative (x + y) / 2 fails for large values.
|
||||
// The alternative (x + y) >>> 1 fails for negative values.
|
||||
return (x & y) + ((x ^ y) >> 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue