mirror of https://github.com/apache/lucene.git
LUCENE-7738: Fix min/max verification bug in InetAddressRange to correctly compare IPv4 and IPv6. Update tests.
This commit is contained in:
parent
cb9f151db4
commit
ef8126e5ea
|
@ -68,9 +68,6 @@ public class InetAddressRange extends Field {
|
|||
* @param max range max value; defined as an {@code InetAddress}
|
||||
*/
|
||||
public void setRangeValues(InetAddress min, InetAddress max) {
|
||||
if (StringHelper.compare(BYTES, min.getAddress(), 0, max.getAddress(), 0) > 0) {
|
||||
throw new IllegalArgumentException("min value cannot be greater than max value for range field (name=" + name + ")");
|
||||
}
|
||||
final byte[] bytes;
|
||||
if (fieldsData == null) {
|
||||
bytes = new byte[BYTES*2];
|
||||
|
@ -83,8 +80,15 @@ public class InetAddressRange extends Field {
|
|||
|
||||
/** encode the min/max range into the provided byte array */
|
||||
private static void encode(final InetAddress min, final InetAddress max, final byte[] bytes) {
|
||||
System.arraycopy(InetAddressPoint.encode(min), 0, bytes, 0, BYTES);
|
||||
System.arraycopy(InetAddressPoint.encode(max), 0, bytes, BYTES, BYTES);
|
||||
// encode min and max value (consistent w/ InetAddressPoint encoding)
|
||||
final byte[] minEncoded = InetAddressPoint.encode(min);
|
||||
final byte[] maxEncoded = InetAddressPoint.encode(max);
|
||||
// ensure min is lt max
|
||||
if (StringHelper.compare(BYTES, minEncoded, 0, maxEncoded, 0) > 0) {
|
||||
throw new IllegalArgumentException("min value cannot be greater than max value for InetAddressRange field");
|
||||
}
|
||||
System.arraycopy(minEncoded, 0, bytes, 0, BYTES);
|
||||
System.arraycopy(maxEncoded, 0, bytes, BYTES, BYTES);
|
||||
}
|
||||
|
||||
/** encode the min/max range and return the byte array */
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.lucene.search;
|
|||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.apache.lucene.document.InetAddressPoint;
|
||||
import org.apache.lucene.document.InetAddressRange;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
|
||||
|
@ -28,16 +29,12 @@ import org.apache.lucene.util.StringHelper;
|
|||
public class TestInetAddressRangeQueries extends BaseRangeFieldQueryTestCase {
|
||||
private static final String FIELD_NAME = "ipRangeField";
|
||||
|
||||
private IPVersion ipVersion;
|
||||
|
||||
private enum IPVersion {IPv4, IPv6}
|
||||
|
||||
@Override
|
||||
protected Range nextRange(int dimensions) throws Exception {
|
||||
InetAddress min = nextInetaddress();
|
||||
byte[] bMin = min.getAddress();
|
||||
byte[] bMin = InetAddressPoint.encode(min);
|
||||
InetAddress max = nextInetaddress();
|
||||
byte[] bMax = max.getAddress();
|
||||
byte[] bMax = InetAddressPoint.encode(max);
|
||||
if (StringHelper.compare(bMin.length, bMin, 0, bMax, 0) > 0) {
|
||||
return new IpRange(max, min);
|
||||
}
|
||||
|
@ -46,89 +43,74 @@ public class TestInetAddressRangeQueries extends BaseRangeFieldQueryTestCase {
|
|||
|
||||
/** return random IPv4 or IPv6 address */
|
||||
private InetAddress nextInetaddress() throws UnknownHostException {
|
||||
byte[] b;
|
||||
switch (ipVersion) {
|
||||
case IPv4:
|
||||
b = new byte[4];
|
||||
break;
|
||||
case IPv6:
|
||||
b = new byte[16];
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("incorrect IP version: " + ipVersion);
|
||||
}
|
||||
byte[] b = random().nextBoolean() ? new byte[4] : new byte[16];
|
||||
random().nextBytes(b);
|
||||
return InetAddress.getByAddress(b);
|
||||
}
|
||||
|
||||
/** randomly select version across tests */
|
||||
private IPVersion ipVersion() {
|
||||
return random().nextBoolean() ? IPVersion.IPv4 : IPVersion.IPv6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testRandomTiny() throws Exception {
|
||||
ipVersion = ipVersion();
|
||||
super.testRandomTiny();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testMultiValued() throws Exception {
|
||||
ipVersion = ipVersion();
|
||||
super.testRandomMedium();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testRandomMedium() throws Exception {
|
||||
ipVersion = ipVersion();
|
||||
super.testMultiValued();
|
||||
}
|
||||
|
||||
@Nightly
|
||||
@Override
|
||||
public void testRandomBig() throws Exception {
|
||||
ipVersion = ipVersion();
|
||||
super.testRandomBig();
|
||||
}
|
||||
|
||||
/** return random range */
|
||||
@Override
|
||||
protected InetAddressRange newRangeField(Range r) {
|
||||
return new InetAddressRange(FIELD_NAME, ((IpRange)r).min, ((IpRange)r).max);
|
||||
return new InetAddressRange(FIELD_NAME, ((IpRange)r).minAddress, ((IpRange)r).maxAddress);
|
||||
}
|
||||
|
||||
/** return random intersects query */
|
||||
@Override
|
||||
protected Query newIntersectsQuery(Range r) {
|
||||
return InetAddressRange.newIntersectsQuery(FIELD_NAME, ((IpRange)r).min, ((IpRange)r).max);
|
||||
return InetAddressRange.newIntersectsQuery(FIELD_NAME, ((IpRange)r).minAddress, ((IpRange)r).maxAddress);
|
||||
}
|
||||
|
||||
/** return random contains query */
|
||||
@Override
|
||||
protected Query newContainsQuery(Range r) {
|
||||
return InetAddressRange.newContainsQuery(FIELD_NAME, ((IpRange)r).min, ((IpRange)r).max);
|
||||
return InetAddressRange.newContainsQuery(FIELD_NAME, ((IpRange)r).minAddress, ((IpRange)r).maxAddress);
|
||||
}
|
||||
|
||||
/** return random within query */
|
||||
@Override
|
||||
protected Query newWithinQuery(Range r) {
|
||||
return InetAddressRange.newWithinQuery(FIELD_NAME, ((IpRange)r).min, ((IpRange)r).max);
|
||||
return InetAddressRange.newWithinQuery(FIELD_NAME, ((IpRange)r).minAddress, ((IpRange)r).maxAddress);
|
||||
}
|
||||
|
||||
/** return random crosses query */
|
||||
@Override
|
||||
protected Query newCrossesQuery(Range r) {
|
||||
return InetAddressRange.newCrossesQuery(FIELD_NAME, ((IpRange)r).min, ((IpRange)r).max);
|
||||
return InetAddressRange.newCrossesQuery(FIELD_NAME, ((IpRange)r).minAddress, ((IpRange)r).maxAddress);
|
||||
}
|
||||
|
||||
/** encapsulated IpRange for test validation */
|
||||
private class IpRange extends Range {
|
||||
InetAddress min;
|
||||
InetAddress max;
|
||||
InetAddress minAddress;
|
||||
InetAddress maxAddress;
|
||||
byte[] min;
|
||||
byte[] max;
|
||||
|
||||
IpRange(InetAddress min, InetAddress max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.minAddress = min;
|
||||
this.maxAddress = max;
|
||||
this.min = InetAddressPoint.encode(min);
|
||||
this.max = InetAddressPoint.encode(max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -138,33 +120,39 @@ public class TestInetAddressRangeQueries extends BaseRangeFieldQueryTestCase {
|
|||
|
||||
@Override
|
||||
protected InetAddress getMin(int dim) {
|
||||
return min;
|
||||
return minAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setMin(int dim, Object val) {
|
||||
byte[] v = ((InetAddress)val).getAddress();
|
||||
InetAddress v = (InetAddress)val;
|
||||
byte[] e = InetAddressPoint.encode(v);
|
||||
|
||||
if (StringHelper.compare(v.length, min.getAddress(), 0, v, 0) < 0) {
|
||||
max = (InetAddress)val;
|
||||
if (StringHelper.compare(e.length, min, 0, e, 0) < 0) {
|
||||
max = e;
|
||||
maxAddress = v;
|
||||
} else {
|
||||
min = (InetAddress) val;
|
||||
min = e;
|
||||
minAddress = v;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InetAddress getMax(int dim) {
|
||||
return max;
|
||||
return maxAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setMax(int dim, Object val) {
|
||||
byte[] v = ((InetAddress)val).getAddress();
|
||||
InetAddress v = (InetAddress)val;
|
||||
byte[] e = InetAddressPoint.encode(v);
|
||||
|
||||
if (StringHelper.compare(v.length, max.getAddress(), 0, v, 0) > 0) {
|
||||
min = (InetAddress)val;
|
||||
if (StringHelper.compare(e.length, max, 0, e, 0) > 0) {
|
||||
min = e;
|
||||
minAddress = v;
|
||||
} else {
|
||||
max = (InetAddress) val;
|
||||
max = e;
|
||||
maxAddress = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,37 +165,31 @@ public class TestInetAddressRangeQueries extends BaseRangeFieldQueryTestCase {
|
|||
@Override
|
||||
protected boolean isDisjoint(Range o) {
|
||||
IpRange other = (IpRange)o;
|
||||
byte[] bMin = min.getAddress();
|
||||
byte[] bMax = max.getAddress();
|
||||
return StringHelper.compare(bMin.length, bMin, 0, other.max.getAddress(), 0) > 0 ||
|
||||
StringHelper.compare(bMax.length, bMax, 0, other.min.getAddress(), 0) < 0;
|
||||
return StringHelper.compare(min.length, min, 0, other.max, 0) > 0 ||
|
||||
StringHelper.compare(max.length, max, 0, other.min, 0) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isWithin(Range o) {
|
||||
IpRange other = (IpRange)o;
|
||||
byte[] bMin = min.getAddress();
|
||||
byte[] bMax = max.getAddress();
|
||||
return StringHelper.compare(bMin.length, bMin, 0, other.min.getAddress(), 0) >= 0 &&
|
||||
StringHelper.compare(bMax.length, bMax, 0, other.max.getAddress(), 0) <= 0;
|
||||
return StringHelper.compare(min.length, min, 0, other.min, 0) >= 0 &&
|
||||
StringHelper.compare(max.length, max, 0, other.max, 0) <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean contains(Range o) {
|
||||
IpRange other = (IpRange)o;
|
||||
byte[] bMin = min.getAddress();
|
||||
byte[] bMax = max.getAddress();
|
||||
return StringHelper.compare(bMin.length, bMin, 0, other.min.getAddress(), 0) <= 0 &&
|
||||
StringHelper.compare(bMax.length, bMax, 0, other.max.getAddress(), 0) >= 0;
|
||||
return StringHelper.compare(min.length, min, 0, other.min, 0) <= 0 &&
|
||||
StringHelper.compare(max.length, max, 0, other.max, 0) >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("Box(");
|
||||
b.append(min.getHostAddress());
|
||||
b.append(minAddress.getHostAddress());
|
||||
b.append(" TO ");
|
||||
b.append(max.getHostAddress());
|
||||
b.append(maxAddress.getHostAddress());
|
||||
b.append(")");
|
||||
return b.toString();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue