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..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 @@ -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); } /** @@ -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 e51fd87c2a057..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 @@ -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; @@ -27,6 +28,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. + */ + static final int MAX_VALUES = 100; + public static ScriptContext newContext(String name, Class factoryClass) { return new ScriptContext( name + "_script_field", @@ -54,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()); @@ -93,5 +101,23 @@ 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( + 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..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 @@ -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); } /** @@ -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 5486fc9307cfb..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 @@ -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); } /** @@ -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/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 40ab2ecd2ded1..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,9 +16,15 @@ 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 { + /** + * 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() { @@ -28,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 { @@ -36,9 +42,10 @@ 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); } /** @@ -49,12 +56,26 @@ 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) { + checkMaxSize(results.size()); + chars += v.length(); + 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..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,10 +6,24 @@ 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 = (params, lookup) -> ctx -> new BooleanScriptFieldScript( + public static final BooleanScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new BooleanScriptFieldScript( + fieldName, params, lookup, ctx @@ -29,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 768f22347f48f..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,10 +6,26 @@ 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 = (params, lookup, formatter) -> ctx -> new DateScriptFieldScript( + public static final DateScriptFieldScript.Factory DUMMY = (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript( + fieldName, params, lookup, formatter, @@ -30,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 4cf222c12eb75..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,10 +6,25 @@ 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 = (params, lookup) -> ctx -> new DoubleScriptFieldScript( + public static final DoubleScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new DoubleScriptFieldScript( + fieldName, params, lookup, ctx @@ -29,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 15d47c6ce39a3..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,10 +6,29 @@ 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 = (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"); @@ -25,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 4dd408e92fe85..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,10 +6,29 @@ 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 = (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); @@ -25,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]") + ); + } + } + } } 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..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 @@ -6,10 +6,25 @@ 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 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 @@ -29,4 +44,61 @@ 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( + "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("test"); + } + } + }; + 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]") + ); + } + } + } + + 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( + "test", + 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(), + 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 c25a31e6e5999..ff402485c196f 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 116769aa04268..04d33aa951b1d 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 8d05a52525ea9..cfaba505d2ad3 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 103ee52beaac7..6b722365083d5 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 @@ -294,7 +294,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")) { @@ -303,7 +303,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 e67bea8a8d614..9193c66f64a0e 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 1d40f5fe21cb0..611ce8f4f3b39 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")) {