Mappings: Validate parsed document does not have trailing garbage that is invalid json

This remerges PR #11414. The added validation for trailing garbage is
now only done when the parse method created the parser.
This commit is contained in:
Ryan Ernst 2015-08-10 23:16:39 -07:00
parent 80cca9e7ad
commit 57549a8133
2 changed files with 25 additions and 0 deletions

View File

@ -25,6 +25,7 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.IndexableField;
import org.apache.lucene.util.CloseableThreadLocal; import org.apache.lucene.util.CloseableThreadLocal;
import org.elasticsearch.Version;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.joda.FormatDateTimeFormatter; import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.settings.Settings; 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.ArrayValueMapperParser;
import org.elasticsearch.index.mapper.object.ObjectMapper; import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.mapper.object.RootObjectMapper; import org.elasticsearch.index.mapper.object.RootObjectMapper;
import org.elasticsearch.percolator.PercolatorService;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
@ -127,6 +129,15 @@ class DocumentParser implements Closeable {
parser.nextToken(); 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) { for (MetadataFieldMapper metadataMapper : mapping.metadataMappers) {
metadataMapper.postParse(context); metadataMapper.postParse(context);
} }

View File

@ -309,4 +309,18 @@ public class DefaultSourceMappingTests extends ESSingleNodeTestCase {
.endObject().endObject().string(); .endObject().endObject().string();
assertFalse(parser.parse(mapping).sourceMapper().isComplete()); 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 '}'"));
}
}
} }