Merge pull request #17260 from talevy/fix-regex-exceptions

Handle regex parsing errors in Gsub and Grok Processors
This commit is contained in:
Tal Levy 2016-03-29 08:12:26 -07:00
commit 16e888fac3
4 changed files with 64 additions and 5 deletions

View File

@ -19,6 +19,7 @@
package org.elasticsearch.ingest.processor; package org.elasticsearch.ingest.processor;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.ingest.core.AbstractProcessor; import org.elasticsearch.ingest.core.AbstractProcessor;
import org.elasticsearch.ingest.core.AbstractProcessorFactory; import org.elasticsearch.ingest.core.AbstractProcessorFactory;
import org.elasticsearch.ingest.core.IngestDocument; import org.elasticsearch.ingest.core.IngestDocument;
@ -28,6 +29,9 @@ import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static org.elasticsearch.ingest.core.ConfigurationUtils.newConfigurationException;
import static org.elasticsearch.ingest.core.ConfigurationUtils.readStringProperty;
/** /**
* Processor that allows to search for patterns in field content and replace them with corresponding string replacement. * Processor that allows to search for patterns in field content and replace them with corresponding string replacement.
* Support fields of string type only, throws exception if a field is of a different type. * Support fields of string type only, throws exception if a field is of a different type.
@ -79,10 +83,15 @@ public final class GsubProcessor extends AbstractProcessor {
public static final class Factory extends AbstractProcessorFactory<GsubProcessor> { public static final class Factory extends AbstractProcessorFactory<GsubProcessor> {
@Override @Override
public GsubProcessor doCreate(String processorTag, Map<String, Object> config) throws Exception { public GsubProcessor doCreate(String processorTag, Map<String, Object> config) throws Exception {
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field"); String field = readStringProperty(TYPE, processorTag, config, "field");
String pattern = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "pattern"); String pattern = readStringProperty(TYPE, processorTag, config, "pattern");
String replacement = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "replacement"); String replacement = readStringProperty(TYPE, processorTag, config, "replacement");
Pattern searchPattern = Pattern.compile(pattern); Pattern searchPattern;
try {
searchPattern = Pattern.compile(pattern);
} catch (Exception e) {
throw newConfigurationException(TYPE, processorTag, "pattern", "Invalid regex pattern. " + e.getMessage());
}
return new GsubProcessor(processorTag, field, searchPattern, replacement); return new GsubProcessor(processorTag, field, searchPattern, replacement);
} }
} }

View File

@ -84,4 +84,18 @@ public class GsubProcessorFactoryTests extends ESTestCase {
assertThat(e.getMessage(), equalTo("[replacement] required property is missing")); assertThat(e.getMessage(), equalTo("[replacement] required property is missing"));
} }
} }
public void testCreateInvalidPattern() throws Exception {
GsubProcessor.Factory factory = new GsubProcessor.Factory();
Map<String, Object> config = new HashMap<>();
config.put("field", "field1");
config.put("pattern", "[");
config.put("replacement", "-");
try {
factory.create(config);
fail("factory create should have failed");
} catch(ElasticsearchParseException e) {
assertThat(e.getMessage(), equalTo("[pattern] Invalid regex pattern. Unclosed character class near index 0\n[\n^"));
}
}
} }

View File

@ -27,6 +27,8 @@ import org.elasticsearch.ingest.core.IngestDocument;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.ingest.core.ConfigurationUtils.newConfigurationException;
public final class GrokProcessor extends AbstractProcessor { public final class GrokProcessor extends AbstractProcessor {
public static final String TYPE = "grok"; public static final String TYPE = "grok";
@ -82,7 +84,12 @@ public final class GrokProcessor extends AbstractProcessor {
patternBank.putAll(customPatternBank); patternBank.putAll(customPatternBank);
} }
Grok grok = new Grok(patternBank, matchPattern); Grok grok;
try {
grok = new Grok(patternBank, matchPattern);
} catch (Exception e) {
throw newConfigurationException(TYPE, processorTag, "pattern", "Invalid regex pattern. " + e.getMessage());
}
return new GrokProcessor(processorTag, grok, matchField); return new GrokProcessor(processorTag, grok, matchField);
} }

View File

@ -84,4 +84,33 @@ public class GrokProcessorFactoryTests extends ESTestCase {
assertThat(processor.getGrok(), notNullValue()); assertThat(processor.getGrok(), notNullValue());
assertThat(processor.getGrok().match("foo!"), equalTo(true)); assertThat(processor.getGrok().match("foo!"), equalTo(true));
} }
public void testCreateWithInvalidPattern() throws Exception {
GrokProcessor.Factory factory = new GrokProcessor.Factory(Collections.emptyMap());
Map<String, Object> config = new HashMap<>();
config.put("field", "_field");
config.put("pattern", "[");
try {
factory.create(config);
fail("should fail");
} catch (ElasticsearchParseException e) {
assertThat(e.getMessage(), equalTo("[pattern] Invalid regex pattern. premature end of char-class"));
}
}
public void testCreateWithInvalidPatternDefinition() throws Exception {
GrokProcessor.Factory factory = new GrokProcessor.Factory(Collections.emptyMap());
Map<String, Object> config = new HashMap<>();
config.put("field", "_field");
config.put("pattern", "%{MY_PATTERN:name}!");
config.put("pattern_definitions", Collections.singletonMap("MY_PATTERN", "["));
try {
factory.create(config);
fail("should fail");
} catch (ElasticsearchParseException e) {
assertThat(e.getMessage(), equalTo("[pattern] Invalid regex pattern. premature end of char-class"));
}
}
} }