diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index e379ea45968..2f68003cc42 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -25,6 +25,7 @@ import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexableField; import org.apache.lucene.util.CloseableThreadLocal; +import org.elasticsearch.Version; import org.elasticsearch.common.Strings; import org.elasticsearch.common.joda.FormatDateTimeFormatter; import org.elasticsearch.common.settings.Settings; @@ -42,6 +43,7 @@ import org.elasticsearch.index.mapper.internal.UidFieldMapper; import org.elasticsearch.index.mapper.object.ArrayValueMapperParser; import org.elasticsearch.index.mapper.object.ObjectMapper; import org.elasticsearch.index.mapper.object.RootObjectMapper; +import org.elasticsearch.percolator.PercolatorService; import java.io.Closeable; import java.io.IOException; @@ -127,6 +129,15 @@ class DocumentParser implements Closeable { parser.nextToken(); } + // try to parse the next token, this should be null if the object is ended properly + // but will throw a JSON exception if the extra tokens is not valid JSON (this will be handled by the catch) + if (Version.indexCreated(indexSettings).onOrAfter(Version.V_2_0_0_beta1) + && source.parser() == null && parser != null) { + // only check for end of tokens if we created the parser here + token = parser.nextToken(); + assert token == null; // double check, in tests, that we didn't end parsing early + } + for (MetadataFieldMapper metadataMapper : mapping.metadataMappers) { metadataMapper.postParse(context); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java index 6e055f7403d..f6a4c30c863 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java @@ -309,4 +309,18 @@ public class DefaultSourceMappingTests extends ESSingleNodeTestCase { .endObject().endObject().string(); assertFalse(parser.parse(mapping).sourceMapper().isComplete()); } + + public void testSourceObjectContainsExtraTokens() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string(); + DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping); + + try { + documentMapper.parse("test", "type", "1", new BytesArray("{}}")); // extra end object (invalid JSON) + fail("Expected parse exception"); + } catch (MapperParsingException e) { + assertNotNull(e.getRootCause()); + String message = e.getRootCause().getMessage(); + assertTrue(message, message.contains("Unexpected close marker '}'")); + } + } }