Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for NPE enclosed in SearchParseException for a "geo_shape" filter or query #8785

Merged
merged 1 commit into from Dec 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -346,6 +346,10 @@ protected CoordinateNode(List<CoordinateNode> children) {
this.coordinate = null;
}

protected boolean isEmpty() {
return (coordinate == null && (children == null || children.isEmpty()));
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (children == null) {
Expand Down Expand Up @@ -607,7 +611,19 @@ public static ShapeBuilder parse(XContentParser parser) throws IOException {
}
}

protected static void validatePointNode(CoordinateNode node) {
if (node.isEmpty()) {
throw new ElasticsearchParseException("Invalid number of points (0) provided when expecting a single coordinate "
+ "([lat, lng])");
} else if (node.coordinate == null) {
if (node.children.isEmpty() == false) {
throw new ElasticsearchParseException("multipoint data provided when single point data expected.");
}
}
}

protected static PointBuilder parsePoint(CoordinateNode node) {
validatePointNode(node);
return newPoint(node.coordinate);
}

Expand All @@ -619,7 +635,24 @@ protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates) {
return newEnvelope().topLeft(coordinates.children.get(0).coordinate).bottomRight(coordinates.children.get(1).coordinate);
}

protected static void validateMultiPointNode(CoordinateNode coordinates) {
if (coordinates.children == null || coordinates.children.isEmpty()) {
if (coordinates.coordinate != null) {
throw new ElasticsearchParseException("single coordinate found when expecting an array of " +
"coordinates. change type to point or change data to an array of >0 coordinates");
}
throw new ElasticsearchParseException("No data provided for multipoint object when expecting " +
">0 points (e.g., [[lat, lng]] or [[lat, lng], ...])");
} else {
for (CoordinateNode point : coordinates.children) {
validatePointNode(point);
}
}
}

protected static MultiPointBuilder parseMultiPoint(CoordinateNode coordinates) {
validateMultiPointNode(coordinates);

MultiPointBuilder points = new MultiPointBuilder();
for (CoordinateNode node : coordinates.children) {
points.point(node.coordinate);
Expand Down Expand Up @@ -671,6 +704,11 @@ protected static LineStringBuilder parseLinearRing(CoordinateNode coordinates) {
}

protected static PolygonBuilder parsePolygon(CoordinateNode coordinates) {
if (coordinates.children == null || coordinates.children.isEmpty()) {
throw new ElasticsearchParseException("Invalid LinearRing provided for type polygon. Linear ring must be an array of " +
"coordinates");
}

LineStringBuilder shell = parseLinearRing(coordinates.children.get(0));
PolygonBuilder polygon = new PolygonBuilder(shell.points);
for (int i = 1; i < coordinates.children.size(); i++) {
Expand Down
Expand Up @@ -157,6 +157,58 @@ public void testParse_polygonNoHoles() throws IOException {
assertGeometryEquals(jtsGeom(expected), polygonGeoJson);
}

@Test
public void testParse_invalidPoint() throws IOException {
// test case 1: create an invalid point object with multipoint data format
String invalidPoint1 = XContentFactory.jsonBuilder().startObject().field("type", "point")
.startArray("coordinates")
.startArray().value(-74.011).value(40.753).endArray()
.endArray()
.endObject().string();
XContentParser parser = JsonXContent.jsonXContent.createParser(invalidPoint1);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchParseException.class);

// test case 2: create an invalid point object with an empty number of coordinates
String invalidPoint2 = XContentFactory.jsonBuilder().startObject().field("type", "point")
.startArray("coordinates")
.endArray()
.endObject().string();
parser = JsonXContent.jsonXContent.createParser(invalidPoint2);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchParseException.class);
}

@Test
public void testParse_invalidMultipoint() throws IOException {
// test case 1: create an invalid multipoint object with single coordinate
String invalidMultipoint1 = XContentFactory.jsonBuilder().startObject().field("type", "multipoint")
.startArray("coordinates").value(-74.011).value(40.753).endArray()
.endObject().string();
XContentParser parser = JsonXContent.jsonXContent.createParser(invalidMultipoint1);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchParseException.class);

// test case 2: create an invalid multipoint object with null coordinate
String invalidMultipoint2 = XContentFactory.jsonBuilder().startObject().field("type", "multipoint")
.startArray("coordinates")
.endArray()
.endObject().string();
parser = JsonXContent.jsonXContent.createParser(invalidMultipoint2);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchParseException.class);

// test case 3: create a valid formatted multipoint object with invalid number (0) of coordinates
String invalidMultipoint3 = XContentFactory.jsonBuilder().startObject().field("type", "multipoint")
.startArray("coordinates")
.startArray().endArray()
.endArray()
.endObject().string();
parser = JsonXContent.jsonXContent.createParser(invalidMultipoint3);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchParseException.class);
}

@Test
public void testParse_invalidPolygon() throws IOException {
/**
Expand Down Expand Up @@ -225,6 +277,15 @@ public void testParse_invalidPolygon() throws IOException {
parser = JsonXContent.jsonXContent.createParser(invalidPoly5);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchIllegalArgumentException.class);

// test case 6: create an invalid polygon with 0 LinearRings
String invalidPoly6 = XContentFactory.jsonBuilder().startObject().field("type", "polygon")
.startArray("coordinates").endArray()
.endObject().string();

parser = JsonXContent.jsonXContent.createParser(invalidPoly6);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, ElasticsearchParseException.class);
}

@Test
Expand Down