From 4fa21cfd90692579192da9519c78e846d5919924 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Thu, 3 Sep 2020 12:39:45 -0400 Subject: [PATCH 1/3] Stop runtime script from emitting too many values This prevent `keyword` valued runtime scripts from emitting too many values or values that take up too much space. Without this you can put allocate a ton of memory with the script by sticking it into a tight loop. Painless has some protections against this but: 1. I don't want to rely on them out of sheer paranoia 2. They don't really kick in when the script uses callbacks like we do anyway. Relates to #59332 --- .../AbstractScriptFieldScript.java | 5 ++ .../StringScriptFieldScript.java | 14 ++++ .../StringScriptFieldScriptTests.java | 64 +++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java index e51fd87c2a057..4481029162012 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java @@ -27,6 +27,11 @@ * {@link AggregationScript} but hopefully with less historical baggage. */ public abstract class AbstractScriptFieldScript { + /** + * The maximum number of values a script should be allowed to emit. + */ + public static final int MAX_VALUES = 1000; + public static ScriptContext newContext(String name, Class factoryClass) { return new ScriptContext( name + "_script_field", diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java index 40ab2ecd2ded1..429f0b2ed3102 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java @@ -19,6 +19,11 @@ import java.util.Map; public abstract class StringScriptFieldScript extends AbstractScriptFieldScript { + /** + * The maximum number of chars a script should be allowed to emit. + */ + public static final long MAX_CHARS = 1024 * 1024; + public static final ScriptContext CONTEXT = newContext("string_script_field", Factory.class); static List whitelist() { @@ -36,6 +41,7 @@ public interface LeafFactory { } private final List results = new ArrayList<>(); + private long chars; public StringScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { super(params, searchLookup, ctx); @@ -49,12 +55,20 @@ public StringScriptFieldScript(Map params, SearchLookup searchLo */ public final List resultsForDoc(int docId) { results.clear(); + chars = 0; setDocument(docId); execute(); return results; } protected final void emitValue(String v) { + if (results.size() >= MAX_VALUES) { + throw new IllegalArgumentException("too many runtime values"); + } + chars += v.length(); + if (chars >= MAX_CHARS) { + throw new IllegalArgumentException("too many characters in runtime values [" + chars + "]"); + } results.add(v); } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java index 7b500f6406eb1..4620051c6bc69 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java @@ -6,7 +6,22 @@ package org.elasticsearch.xpack.runtimefields; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; +import static org.mockito.Mockito.mock; public class StringScriptFieldScriptTests extends ScriptFieldScriptTestCase { public static final StringScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new StringScriptFieldScript( @@ -29,4 +44,53 @@ protected ScriptContext context() { protected StringScriptFieldScript.Factory dummyScript() { return DUMMY; } + + public void testTooManyValues() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + StringScriptFieldScript script = new StringScriptFieldScript( + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + reader.leaves().get(0) + ) { + @Override + public void execute() { + for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) { + emitValue("test"); + } + } + }; + Exception e = expectThrows(IllegalArgumentException.class, script::execute); + assertThat(e.getMessage(), equalTo("too many runtime values")); + } + } + } + + public void testTooManyChars() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + StringScriptFieldScript script = new StringScriptFieldScript( + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + reader.leaves().get(0) + ) { + @Override + public void execute() { + StringBuilder big = new StringBuilder(); + while (big.length() < StringScriptFieldScript.MAX_CHARS / 4) { + big.append("test"); + } + String bigString = big.toString(); + for (int i = 0; i <= 4; i++) { + emitValue(bigString); + } + } + }; + Exception e = expectThrows(IllegalArgumentException.class, script::execute); + assertThat(e.getMessage(), startsWith("too many characters in runtime values [")); + } + } + } } From bb5abb9995283c5b491fc8d9194198f91fe68dc9 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Fri, 4 Sep 2020 11:25:43 -0400 Subject: [PATCH 2/3] Name name name --- .../AbstractLongScriptFieldScript.java | 4 ++-- .../AbstractScriptFieldScript.java | 21 +++++++++++++++-- .../BooleanScriptFieldScript.java | 6 ++--- .../runtimefields/DateScriptFieldScript.java | 12 +++++++--- .../DoubleScriptFieldScript.java | 6 ++--- .../runtimefields/IpScriptFieldScript.java | 6 ++--- .../runtimefields/LongScriptFieldScript.java | 6 ++--- .../StringScriptFieldScript.java | 23 ++++++++++++------- .../mapper/ScriptBooleanMappedFieldType.java | 2 +- .../mapper/ScriptDateMappedFieldType.java | 2 +- .../mapper/ScriptDoubleMappedFieldType.java | 2 +- .../mapper/ScriptIpMappedFieldType.java | 2 +- .../mapper/ScriptKeywordMappedFieldType.java | 2 +- .../mapper/ScriptLongMappedFieldType.java | 2 +- .../BooleanScriptFieldScriptTests.java | 3 ++- .../DateScriptFieldScriptTests.java | 3 ++- .../DoubleScriptFieldScriptTests.java | 3 ++- .../IpScriptFieldScriptTests.java | 7 +++++- .../LongScriptFieldScriptTests.java | 7 +++++- .../StringScriptFieldScriptTests.java | 16 +++++++++---- .../ScriptBooleanMappedFieldTypeTests.java | 14 +++++++++-- .../ScriptDateMappedFieldTypeTests.java | 16 +++++++++++-- .../ScriptDoubleMappedFieldTypeTests.java | 4 ++-- .../mapper/ScriptIpMappedFieldTypeTests.java | 4 ++-- .../ScriptKeywordMappedFieldTypeTests.java | 4 ++-- .../ScriptLongMappedFieldTypeTests.java | 6 ++--- ...gScriptFieldDistanceFeatureQueryTests.java | 2 +- 27 files changed, 129 insertions(+), 56 deletions(-) diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java index d7b261a4fae78..299216c5a9aff 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java @@ -19,8 +19,8 @@ public abstract class AbstractLongScriptFieldScript extends AbstractScriptFieldS private long[] values = new long[1]; private int count; - public AbstractLongScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public AbstractLongScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(fieldName, params, searchLookup, ctx); } /** diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java index 4481029162012..ae0fce59d7192 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java @@ -17,6 +17,7 @@ import org.elasticsearch.search.lookup.SourceLookup; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.function.Function; @@ -30,7 +31,7 @@ public abstract class AbstractScriptFieldScript { /** * The maximum number of values a script should be allowed to emit. */ - public static final int MAX_VALUES = 1000; + static final int MAX_VALUES = 100; public static ScriptContext newContext(String name, Class factoryClass) { return new ScriptContext( @@ -59,10 +60,12 @@ public static ScriptContext newContext(String name, Class factoryClass value -> ((SourceLookup) value).loadSourceIfNeeded() ); + protected final String fieldName; private final Map params; private final LeafSearchLookup leafSearchLookup; - public AbstractScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + public AbstractScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + this.fieldName = fieldName; this.leafSearchLookup = searchLookup.getLeafSearchLookup(ctx); params = new HashMap<>(params); params.put("_source", leafSearchLookup.source()); @@ -98,5 +101,19 @@ public final Map> getDoc() { return leafSearchLookup.doc(); } + protected final void checkMaxSize(int currentSize) { + if (currentSize >= MAX_VALUES) { + throw new IllegalArgumentException( + String.format( + Locale.ROOT, + "Runtime field [%s] is emitting [%s] values while the maximum number of values allowed is [%s]", + fieldName, + currentSize + 1, + MAX_VALUES + ) + ); + } + } + public abstract void execute(); } diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScript.java index 2378877af1aae..9cd8237dece46 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScript.java @@ -28,7 +28,7 @@ static List whitelist() { public static final String[] PARAMETERS = {}; public interface Factory extends ScriptFactory { - LeafFactory newFactory(Map params, SearchLookup searchLookup); + LeafFactory newFactory(String fieldName, Map params, SearchLookup searchLookup); } public interface LeafFactory { @@ -38,8 +38,8 @@ public interface LeafFactory { private int trues; private int falses; - public BooleanScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public BooleanScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(fieldName, params, searchLookup, ctx); } /** diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScript.java index 1ac65a35f2788..6b117d9f7a4f6 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScript.java @@ -30,7 +30,7 @@ static List whitelist() { public static final String[] PARAMETERS = {}; public interface Factory extends ScriptFactory { - LeafFactory newFactory(Map params, SearchLookup searchLookup, DateFormatter formatter); + LeafFactory newFactory(String fieldName, Map params, SearchLookup searchLookup, DateFormatter formatter); } public interface LeafFactory { @@ -39,8 +39,14 @@ public interface LeafFactory { private final DateFormatter formatter; - public DateScriptFieldScript(Map params, SearchLookup searchLookup, DateFormatter formatter, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public DateScriptFieldScript( + String fieldName, + Map params, + SearchLookup searchLookup, + DateFormatter formatter, + LeafReaderContext ctx + ) { + super(fieldName, params, searchLookup, ctx); this.formatter = formatter; } diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java index 03172e983965c..8e922239a159a 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java @@ -28,7 +28,7 @@ static List whitelist() { public static final String[] PARAMETERS = {}; public interface Factory extends ScriptFactory { - LeafFactory newFactory(Map params, SearchLookup searchLookup); + LeafFactory newFactory(String fieldName, Map params, SearchLookup searchLookup); } public interface LeafFactory { @@ -38,8 +38,8 @@ public interface LeafFactory { private double[] values = new double[1]; private int count; - public DoubleScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public DoubleScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(fieldName, params, searchLookup, ctx); } /** diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java index 5486fc9307cfb..24acbd278b7f4 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java @@ -49,7 +49,7 @@ static List whitelist() { public static final String[] PARAMETERS = {}; public interface Factory extends ScriptFactory { - LeafFactory newFactory(Map params, SearchLookup searchLookup); + LeafFactory newFactory(String fieldName, Map params, SearchLookup searchLookup); } public interface LeafFactory { @@ -59,8 +59,8 @@ public interface LeafFactory { private BytesRef[] values = new BytesRef[1]; private int count; - public IpScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public IpScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(fieldName, params, searchLookup, ctx); } /** diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScript.java index 1ad0c2b40bb70..a5870e6dd5029 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScript.java @@ -27,15 +27,15 @@ static List whitelist() { public static final String[] PARAMETERS = {}; public interface Factory extends ScriptFactory { - LeafFactory newFactory(Map params, SearchLookup searchLookup); + LeafFactory newFactory(String fieldName, Map params, SearchLookup searchLookup); } public interface LeafFactory { LongScriptFieldScript newInstance(LeafReaderContext ctx) throws IOException; } - public LongScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public LongScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(fieldName, params, searchLookup, ctx); } public static class EmitValue { diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java index 429f0b2ed3102..666c271f4301d 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScript.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public abstract class StringScriptFieldScript extends AbstractScriptFieldScript { @@ -33,7 +34,7 @@ static List whitelist() { public static final String[] PARAMETERS = {}; public interface Factory extends ScriptFactory { - LeafFactory newFactory(Map params, SearchLookup searchLookup); + LeafFactory newFactory(String fieldName, Map params, SearchLookup searchLookup); } public interface LeafFactory { @@ -43,8 +44,8 @@ public interface LeafFactory { private final List results = new ArrayList<>(); private long chars; - public StringScriptFieldScript(Map params, SearchLookup searchLookup, LeafReaderContext ctx) { - super(params, searchLookup, ctx); + public StringScriptFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(fieldName, params, searchLookup, ctx); } /** @@ -62,12 +63,18 @@ public final List resultsForDoc(int docId) { } protected final void emitValue(String v) { - if (results.size() >= MAX_VALUES) { - throw new IllegalArgumentException("too many runtime values"); - } + checkMaxSize(results.size()); chars += v.length(); - if (chars >= MAX_CHARS) { - throw new IllegalArgumentException("too many characters in runtime values [" + chars + "]"); + if (chars > MAX_CHARS) { + throw new IllegalArgumentException( + String.format( + Locale.ROOT, + "Runtime field [%s] is emitting [%s] characters while the maximum number of values allowed is [%s]", + fieldName, + chars, + MAX_CHARS + ) + ); } results.add(v); } diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldType.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldType.java index 8af187f543567..98b5820078233 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldType.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldType.java @@ -72,7 +72,7 @@ public ScriptBooleanFieldData.Builder fielddataBuilder(String fullyQualifiedInde } private BooleanScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) { - return scriptFactory.newFactory(script.getParams(), searchLookup); + return scriptFactory.newFactory(name(), script.getParams(), searchLookup); } @Override diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldType.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldType.java index 904a35ca3f827..8395508e91675 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldType.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldType.java @@ -85,7 +85,7 @@ public ScriptDateFieldData.Builder fielddataBuilder(String fullyQualifiedIndexNa } private DateScriptFieldScript.LeafFactory leafFactory(SearchLookup lookup) { - return scriptFactory.newFactory(script.getParams(), lookup, dateTimeFormatter); + return scriptFactory.newFactory(name(), script.getParams(), lookup, dateTimeFormatter); } @Override diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldType.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldType.java index e835d45f861f2..bc898bbfa23f3 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldType.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldType.java @@ -64,7 +64,7 @@ public ScriptDoubleFieldData.Builder fielddataBuilder(String fullyQualifiedIndex } private DoubleScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) { - return scriptFactory.newFactory(script.getParams(), searchLookup); + return scriptFactory.newFactory(name(), script.getParams(), searchLookup); } @Override diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldType.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldType.java index 762c134a0e09e..0257fa116c2dd 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldType.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldType.java @@ -80,7 +80,7 @@ public ScriptIpFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName } private IpScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) { - return scriptFactory.newFactory(script.getParams(), searchLookup); + return scriptFactory.newFactory(name(), script.getParams(), searchLookup); } @Override diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldType.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldType.java index f41c053f7d580..3341f7c4ed00c 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldType.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldType.java @@ -68,7 +68,7 @@ public ScriptStringFieldData.Builder fielddataBuilder(String fullyQualifiedIndex } private StringScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) { - return scriptFactory.newFactory(script.getParams(), searchLookup); + return scriptFactory.newFactory(name(), script.getParams(), searchLookup); } @Override diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldType.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldType.java index 24ecde240c3f1..0568ee4e9e7ba 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldType.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldType.java @@ -64,7 +64,7 @@ public ScriptLongFieldData.Builder fielddataBuilder(String fullyQualifiedIndexNa } private LongScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) { - return scriptFactory.newFactory(script.getParams(), searchLookup); + return scriptFactory.newFactory(name(), script.getParams(), searchLookup); } @Override diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java index 0f55db05b996b..43c37a430f59b 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java @@ -9,7 +9,8 @@ import org.elasticsearch.script.ScriptContext; public class BooleanScriptFieldScriptTests extends ScriptFieldScriptTestCase { - public static final BooleanScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new BooleanScriptFieldScript( + public static final BooleanScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new BooleanScriptFieldScript( + fieldName, params, lookup, ctx diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java index 768f22347f48f..cd4e2ef48a793 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java @@ -9,7 +9,8 @@ import org.elasticsearch.script.ScriptContext; public class DateScriptFieldScriptTests extends ScriptFieldScriptTestCase { - public static final DateScriptFieldScript.Factory DUMMY = (params, lookup, formatter) -> ctx -> new DateScriptFieldScript( + public static final DateScriptFieldScript.Factory DUMMY = (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript( + fieldName, params, lookup, formatter, diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java index 4cf222c12eb75..36f42c429ba59 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java @@ -9,7 +9,8 @@ import org.elasticsearch.script.ScriptContext; public class DoubleScriptFieldScriptTests extends ScriptFieldScriptTestCase { - public static final DoubleScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new DoubleScriptFieldScript( + public static final DoubleScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new DoubleScriptFieldScript( + fieldName, params, lookup, ctx diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java index 15d47c6ce39a3..836126ce10e0a 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java @@ -9,7 +9,12 @@ import org.elasticsearch.script.ScriptContext; public class IpScriptFieldScriptTests extends ScriptFieldScriptTestCase { - public static final IpScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new IpScriptFieldScript(params, lookup, ctx) { + public static final IpScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new IpScriptFieldScript( + fieldName, + params, + lookup, + ctx + ) { @Override public void execute() { emitValue("192.168.0.1"); diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java index 4dd408e92fe85..733354ccdb67a 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java @@ -9,7 +9,12 @@ import org.elasticsearch.script.ScriptContext; public class LongScriptFieldScriptTests extends ScriptFieldScriptTestCase { - public static final LongScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new LongScriptFieldScript(params, lookup, ctx) { + public static final LongScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new LongScriptFieldScript( + fieldName, + params, + lookup, + ctx + ) { @Override public void execute() { emitValue(1); diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java index 4620051c6bc69..efa957742fd45 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/StringScriptFieldScriptTests.java @@ -20,11 +20,11 @@ import java.util.Map; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.startsWith; import static org.mockito.Mockito.mock; public class StringScriptFieldScriptTests extends ScriptFieldScriptTestCase { - public static final StringScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new StringScriptFieldScript( + public static final StringScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new StringScriptFieldScript( + fieldName, params, lookup, ctx @@ -50,6 +50,7 @@ public void testTooManyValues() throws IOException { iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); try (DirectoryReader reader = iw.getReader()) { StringScriptFieldScript script = new StringScriptFieldScript( + "test", Map.of(), new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), reader.leaves().get(0) @@ -62,7 +63,10 @@ public void execute() { } }; Exception e = expectThrows(IllegalArgumentException.class, script::execute); - assertThat(e.getMessage(), equalTo("too many runtime values")); + assertThat( + e.getMessage(), + equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]") + ); } } } @@ -72,6 +76,7 @@ public void testTooManyChars() throws IOException { iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); try (DirectoryReader reader = iw.getReader()) { StringScriptFieldScript script = new StringScriptFieldScript( + "test", Map.of(), new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), reader.leaves().get(0) @@ -89,7 +94,10 @@ public void execute() { } }; Exception e = expectThrows(IllegalArgumentException.class, script::execute); - assertThat(e.getMessage(), startsWith("too many characters in runtime values [")); + assertThat( + e.getMessage(), + equalTo("Runtime field [test] is emitting [1310720] characters while the maximum number of values allowed is [1048576]") + ); } } } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldTypeTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldTypeTests.java index 8db96f0c0ff15..a8141aab2099b 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldTypeTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptBooleanMappedFieldTypeTests.java @@ -409,7 +409,12 @@ public FactoryType compile( private BooleanScriptFieldScript.Factory factory(String code) { switch (code) { case "read_foo": - return (params, lookup) -> (ctx) -> new BooleanScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new BooleanScriptFieldScript( + fieldName, + params, + lookup, + ctx + ) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { @@ -418,7 +423,12 @@ public void execute() { } }; case "xor_param": - return (params, lookup) -> (ctx) -> new BooleanScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new BooleanScriptFieldScript( + fieldName, + params, + lookup, + ctx + ) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldTypeTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldTypeTests.java index 271d4d37a46e6..85e4331670603 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldTypeTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDateMappedFieldTypeTests.java @@ -439,7 +439,13 @@ public FactoryType compile( private DateScriptFieldScript.Factory factory(String code) { switch (code) { case "read_timestamp": - return (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(params, lookup, formatter, ctx) { + return (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript( + fieldName, + params, + lookup, + formatter, + ctx + ) { @Override public void execute() { for (Object timestamp : (List) getSource().get("timestamp")) { @@ -449,7 +455,13 @@ public void execute() { } }; case "add_days": - return (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(params, lookup, formatter, ctx) { + return (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript( + fieldName, + params, + lookup, + formatter, + ctx + ) { @Override public void execute() { for (Object timestamp : (List) getSource().get("timestamp")) { diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldTypeTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldTypeTests.java index 877d27a818239..9a30f3ac81811 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldTypeTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptDoubleMappedFieldTypeTests.java @@ -277,7 +277,7 @@ public FactoryType compile( private DoubleScriptFieldScript.Factory factory(String code) { switch (code) { case "read_foo": - return (params, lookup) -> (ctx) -> new DoubleScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new DoubleScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { @@ -286,7 +286,7 @@ public void execute() { } }; case "add_param": - return (params, lookup) -> (ctx) -> new DoubleScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new DoubleScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldTypeTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldTypeTests.java index f33e1439612f1..37a1a6cfbf529 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldTypeTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptIpMappedFieldTypeTests.java @@ -297,7 +297,7 @@ public FactoryType compile( private IpScriptFieldScript.Factory factory(String code) { switch (code) { case "read_foo": - return (params, lookup) -> (ctx) -> new IpScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new IpScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { @@ -306,7 +306,7 @@ public void execute() { } }; case "append_param": - return (params, lookup) -> (ctx) -> new IpScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new IpScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldTypeTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldTypeTests.java index de0244ef32035..e716a1e978504 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldTypeTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptKeywordMappedFieldTypeTests.java @@ -371,7 +371,7 @@ public FactoryType compile( private StringScriptFieldScript.Factory factory(String code) { switch (code) { case "read_foo": - return (params, lookup) -> (ctx) -> new StringScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> ctx -> new StringScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { @@ -380,7 +380,7 @@ public void execute() { } }; case "append_param": - return (params, lookup) -> (ctx) -> new StringScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> ctx -> new StringScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldTypeTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldTypeTests.java index 2dcd33280b4f1..8582a04e2e0ff 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldTypeTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptLongMappedFieldTypeTests.java @@ -299,7 +299,7 @@ public FactoryType compile( private LongScriptFieldScript.Factory factory(String code) { switch (code) { case "read_foo": - return (params, lookup) -> (ctx) -> new LongScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new LongScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { @@ -308,7 +308,7 @@ public void execute() { } }; case "add_param": - return (params, lookup) -> (ctx) -> new LongScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new LongScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object foo : (List) getSource().get("foo")) { @@ -319,7 +319,7 @@ public void execute() { case "millis_ago": // Painless actually call System.currentTimeMillis. We could mock the time but this works fine too. long now = System.currentTimeMillis(); - return (params, lookup) -> (ctx) -> new LongScriptFieldScript(params, lookup, ctx) { + return (fieldName, params, lookup) -> (ctx) -> new LongScriptFieldScript(fieldName, params, lookup, ctx) { @Override public void execute() { for (Object timestamp : (List) getSource().get("timestamp")) { diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/query/LongScriptFieldDistanceFeatureQueryTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/query/LongScriptFieldDistanceFeatureQueryTests.java index 224195ef11c5d..2f0dd35c80e7d 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/query/LongScriptFieldDistanceFeatureQueryTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/query/LongScriptFieldDistanceFeatureQueryTests.java @@ -87,7 +87,7 @@ public void testMatches() throws IOException { try (DirectoryReader reader = iw.getReader()) { IndexSearcher searcher = newSearcher(reader); CheckedFunction leafFactory = - ctx -> new DateScriptFieldScript(Map.of(), new SearchLookup(null, null), null, ctx) { + ctx -> new DateScriptFieldScript("test", Map.of(), new SearchLookup(null, null), null, ctx) { @Override public void execute() { for (Object timestamp : (List) getSource().get("timestamp")) { From 563b2b7473249c5a54f0e995ff8a91097a39ce33 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Wed, 9 Sep 2020 10:35:54 -0400 Subject: [PATCH 3/3] check limits all places --- .../AbstractLongScriptFieldScript.java | 1 + .../AbstractScriptFieldScript.java | 4 ++ .../DoubleScriptFieldScript.java | 1 + .../runtimefields/IpScriptFieldScript.java | 1 + .../BooleanScriptFieldScriptTests.java | 36 ++++++++++++++++ .../DateScriptFieldScriptTests.java | 42 +++++++++++++++++++ .../DoubleScriptFieldScriptTests.java | 40 ++++++++++++++++++ .../IpScriptFieldScriptTests.java | 40 ++++++++++++++++++ .../LongScriptFieldScriptTests.java | 40 ++++++++++++++++++ 9 files changed, 205 insertions(+) diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java index 299216c5a9aff..93c6ad382d265 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractLongScriptFieldScript.java @@ -50,6 +50,7 @@ public final int count() { } protected final void emitValue(long v) { + checkMaxSize(count); if (values.length < count + 1) { values = ArrayUtil.grow(values, count + 1); } diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java index ae0fce59d7192..a1e084400f00a 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/AbstractScriptFieldScript.java @@ -101,6 +101,10 @@ public final Map> getDoc() { return leafSearchLookup.doc(); } + /** + * Check if the we can add another value to the list of values. + * @param currentSize the current size of the list + */ protected final void checkMaxSize(int currentSize) { if (currentSize >= MAX_VALUES) { throw new IllegalArgumentException( diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java index 8e922239a159a..d9f14f9cdc2ad 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScript.java @@ -69,6 +69,7 @@ public final int count() { } protected final void emitValue(double v) { + checkMaxSize(count); if (values.length < count + 1) { values = ArrayUtil.grow(values, count + 1); } diff --git a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java index 24acbd278b7f4..f93d5db23519c 100644 --- a/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java +++ b/x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScript.java @@ -93,6 +93,7 @@ public final int count() { } protected final void emitValue(String v) { + checkMaxSize(count); if (values.length < count + 1) { values = ArrayUtil.grow(values, count + 1); } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java index 43c37a430f59b..87dd134e3981a 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/BooleanScriptFieldScriptTests.java @@ -6,7 +6,20 @@ package org.elasticsearch.xpack.runtimefields; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.mockito.Mockito.mock; public class BooleanScriptFieldScriptTests extends ScriptFieldScriptTestCase { public static final BooleanScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new BooleanScriptFieldScript( @@ -30,4 +43,27 @@ protected ScriptContext context() { protected BooleanScriptFieldScript.Factory dummyScript() { return DUMMY; } + + public void testTooManyValues() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + BooleanScriptFieldScript script = new BooleanScriptFieldScript( + "test", + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + reader.leaves().get(0) + ) { + @Override + public void execute() { + for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES * 1000; i++) { + emitValue(i % 2 == 0); + } + } + }; + // There isn't a limit to the number of values so this won't throw + script.execute(); + } + } + } } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java index cd4e2ef48a793..24e3f281242d8 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DateScriptFieldScriptTests.java @@ -6,7 +6,22 @@ package org.elasticsearch.xpack.runtimefields; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.time.DateFormatter; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; public class DateScriptFieldScriptTests extends ScriptFieldScriptTestCase { public static final DateScriptFieldScript.Factory DUMMY = (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript( @@ -31,4 +46,31 @@ protected ScriptContext context() { protected DateScriptFieldScript.Factory dummyScript() { return DUMMY; } + + public void testTooManyValues() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + DateScriptFieldScript script = new DateScriptFieldScript( + "test", + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + DateFormatter.forPattern(randomDateFormatterPattern()).withLocale(randomLocale(random())), + reader.leaves().get(0) + ) { + @Override + public void execute() { + for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) { + emitValue(0); + } + } + }; + Exception e = expectThrows(IllegalArgumentException.class, script::execute); + assertThat( + e.getMessage(), + equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]") + ); + } + } + } } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java index 36f42c429ba59..f3f3327c39b82 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/DoubleScriptFieldScriptTests.java @@ -6,7 +6,21 @@ package org.elasticsearch.xpack.runtimefields; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; public class DoubleScriptFieldScriptTests extends ScriptFieldScriptTestCase { public static final DoubleScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new DoubleScriptFieldScript( @@ -30,4 +44,30 @@ protected ScriptContext context() { protected DoubleScriptFieldScript.Factory dummyScript() { return DUMMY; } + + public void testTooManyValues() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + DoubleScriptFieldScript script = new DoubleScriptFieldScript( + "test", + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + reader.leaves().get(0) + ) { + @Override + public void execute() { + for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) { + emitValue(1.0); + } + } + }; + Exception e = expectThrows(IllegalArgumentException.class, script::execute); + assertThat( + e.getMessage(), + equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]") + ); + } + } + } } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java index 836126ce10e0a..e6eb7a5f07e64 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/IpScriptFieldScriptTests.java @@ -6,7 +6,21 @@ package org.elasticsearch.xpack.runtimefields; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; public class IpScriptFieldScriptTests extends ScriptFieldScriptTestCase { public static final IpScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new IpScriptFieldScript( @@ -30,4 +44,30 @@ protected ScriptContext context() { protected IpScriptFieldScript.Factory dummyScript() { return DUMMY; } + + public void testTooManyValues() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + IpScriptFieldScript script = new IpScriptFieldScript( + "test", + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + reader.leaves().get(0) + ) { + @Override + public void execute() { + for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) { + emitValue("192.168.0.1"); + } + } + }; + Exception e = expectThrows(IllegalArgumentException.class, script::execute); + assertThat( + e.getMessage(), + equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]") + ); + } + } + } } diff --git a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java index 733354ccdb67a..570ee0417469c 100644 --- a/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java +++ b/x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/LongScriptFieldScriptTests.java @@ -6,7 +6,21 @@ package org.elasticsearch.xpack.runtimefields; +import org.apache.lucene.document.StoredField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.RandomIndexWriter; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; public class LongScriptFieldScriptTests extends ScriptFieldScriptTestCase { public static final LongScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new LongScriptFieldScript( @@ -30,4 +44,30 @@ protected ScriptContext context() { protected LongScriptFieldScript.Factory dummyScript() { return DUMMY; } + + public void testTooManyValues() throws IOException { + try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) { + iw.addDocument(List.of(new StoredField("_source", new BytesRef("{}")))); + try (DirectoryReader reader = iw.getReader()) { + LongScriptFieldScript script = new LongScriptFieldScript( + "test", + Map.of(), + new SearchLookup(mock(MapperService.class), (ft, lookup) -> null), + reader.leaves().get(0) + ) { + @Override + public void execute() { + for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) { + emitValue(0); + } + } + }; + Exception e = expectThrows(IllegalArgumentException.class, script::execute); + assertThat( + e.getMessage(), + equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]") + ); + } + } + } }