From facd3ee6891748dfb88754c7bfbc171ca076e53c Mon Sep 17 00:00:00 2001 From: "lei.lei" Date: Wed, 20 Jun 2018 14:14:28 +0800 Subject: [PATCH] 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). --- .../java/org/lionsoul/ip2region/DbSearcher.java | 8 ++++---- .../main/java/org/lionsoul/ip2region/Util.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java b/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java index 5bc8e8f..b7721ef 100644 --- a/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java +++ b/binding/java/src/main/java/org/lionsoul/ip2region/DbSearcher.java @@ -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); diff --git a/binding/java/src/main/java/org/lionsoul/ip2region/Util.java b/binding/java/src/main/java/org/lionsoul/ip2region/Util.java index f94d3ee..0044e18 100644 --- a/binding/java/src/main/java/org/lionsoul/ip2region/Util.java +++ b/binding/java/src/main/java/org/lionsoul/ip2region/Util.java @@ -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); + } }