diff --git a/server/src/main/java/org/elasticsearch/common/geo/GeoPoint.java b/server/src/main/java/org/elasticsearch/common/geo/GeoPoint.java index eceeedf9941..0b7b4f7484b 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/GeoPoint.java +++ b/server/src/main/java/org/elasticsearch/common/geo/GeoPoint.java @@ -97,8 +97,18 @@ public final class GeoPoint implements ToXContentFragment { throw new ElasticsearchParseException("failed to parse [{}], expected 2 or 3 coordinates " + "but found: [{}]", vals.length); } - double lat = Double.parseDouble(vals[0].trim()); - double lon = Double.parseDouble(vals[1].trim()); + final double lat; + final double lon; + try { + lat = Double.parseDouble(vals[0].trim()); + } catch (NumberFormatException ex) { + throw new ElasticsearchParseException("latitude must be a number"); + } + try { + lon = Double.parseDouble(vals[1].trim()); + } catch (NumberFormatException ex) { + throw new ElasticsearchParseException("longitude must be a number"); + } if (vals.length > 2) { GeoPoint.assertZValue(ignoreZValue, Double.parseDouble(vals[2].trim())); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index 587e9abd50b..2880169edb5 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -260,7 +260,11 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper throw new IllegalArgumentException("illegal longitude value [" + point.lon() + "] for " + name()); } } else { - GeoUtils.normalizePoint(point); + if (isNormalizable(point.lat()) && isNormalizable(point.lon())) { + GeoUtils.normalizePoint(point); + } else { + throw new ElasticsearchParseException("cannot normalize the point - not a number"); + } } if (fieldType().indexOptions() != IndexOptions.NONE) { context.doc().add(new LatLonPoint(fieldType().name(), point.lat(), point.lon())); @@ -386,4 +390,8 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper public Explicit ignoreZValue() { return ignoreZValue; } + + private boolean isNormalizable(double coord) { + return Double.isNaN(coord) == false && Double.isInfinite(coord) == false; + } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java index b3474fb5efb..8d2f0008992 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java @@ -456,4 +456,72 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { assertThat(ex.getRootCause().getMessage(), equalTo("unsupported symbol [.] in geohash [1234.333]")); } + + public void testInvalidGeopointValuesIgnored() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_point") + .field("ignore_malformed", "true") + .endObject() + .endObject().endObject().endObject()); + + DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() + .parse("type", new CompressedXContent(mapping)); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("location", "1234.333").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("lat", "-").field("lon", 1.3).endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("lat", 1.3).field("lon", "-").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("location", "-,1.3").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("location", "1.3,-").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("lat", "NaN").field("lon", "NaN").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("lat", 12).field("lon", "NaN").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("lat", "NaN").field("lon", 10).endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("location", "NaN,NaN").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("location", "10,NaN").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + + assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1", + BytesReference.bytes(XContentFactory.jsonBuilder() + .startObject().field("location", "NaN,12").endObject() + ), XContentType.JSON)).rootDoc().getField("location"), nullValue()); + } }