4848
4949import java .io .Closeable ;
5050import java .io .IOException ;
51+ import java .nio .charset .StandardCharsets ;
5152import java .util .Collections ;
5253import java .util .HashSet ;
5354import java .util .List ;
@@ -97,8 +98,7 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
9798 public static final Setting <TimeValue > SCRIPT_CACHE_EXPIRE_SETTING =
9899 Setting .positiveTimeSetting ("script.cache.expire" , TimeValue .timeValueMillis (0 ), Property .NodeScope );
99100 public static final Setting <Integer > SCRIPT_MAX_SIZE_IN_BYTES =
100- Setting .intSetting ("script.max_size_in_bytes" , 65535 , Property .NodeScope );
101- // public Setting(String key, Function<Settings, String> defaultValue, Function<String, T> parser, Property... properties) {
101+ Setting .intSetting ("script.max_size_in_bytes" , 65535 , 0 , Property .Dynamic , Property .NodeScope );
102102 public static final Setting <Tuple <Integer , TimeValue >> SCRIPT_MAX_COMPILATIONS_RATE =
103103 new Setting <>("script.max_compilations_rate" , "75/5m" , MAX_COMPILATION_RATE_FUNCTION , Property .Dynamic , Property .NodeScope );
104104
@@ -122,6 +122,8 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
122122
123123 private ClusterState clusterState ;
124124
125+ private int maxSizeInBytes ;
126+
125127 private Tuple <Integer , TimeValue > rate ;
126128 private long lastInlineCompileTime ;
127129 private double scriptsPerTimeWindow ;
@@ -220,10 +222,12 @@ public ScriptService(Settings settings, Map<String, ScriptEngine> engines, Map<S
220222 this .cache = cacheBuilder .removalListener (new ScriptCacheRemovalListener ()).build ();
221223
222224 this .lastInlineCompileTime = System .nanoTime ();
225+ this .setMaxSizeInBytes (SCRIPT_MAX_SIZE_IN_BYTES .get (settings ));
223226 this .setMaxCompilationRate (SCRIPT_MAX_COMPILATIONS_RATE .get (settings ));
224227 }
225228
226229 void registerClusterSettingsListeners (ClusterSettings clusterSettings ) {
230+ clusterSettings .addSettingsUpdateConsumer (SCRIPT_MAX_SIZE_IN_BYTES , this ::setMaxSizeInBytes );
227231 clusterSettings .addSettingsUpdateConsumer (SCRIPT_MAX_COMPILATIONS_RATE , this ::setMaxCompilationRate );
228232 }
229233
@@ -240,6 +244,22 @@ private ScriptEngine getEngine(String lang) {
240244 return scriptEngine ;
241245 }
242246
247+ /**
248+ * Changes the maximum number of bytes a script's source is allowed to have.
249+ * @param newMaxSizeInBytes The new maximum number of bytes.
250+ */
251+ void setMaxSizeInBytes (int newMaxSizeInBytes ) {
252+ for (Map .Entry <String , StoredScriptSource > source : getScriptsFromClusterState ().entrySet ()) {
253+ if (source .getValue ().getSource ().getBytes (StandardCharsets .UTF_8 ).length > newMaxSizeInBytes ) {
254+ throw new IllegalArgumentException ("script.max_size_in_bytes cannot be set to [" + newMaxSizeInBytes + "], " +
255+ "stored script [" + source .getKey () + "] exceeds the new value with a size of " +
256+ "[" + source .getValue ().getSource ().getBytes (StandardCharsets .UTF_8 ).length + "]" );
257+ }
258+ }
259+
260+ maxSizeInBytes = newMaxSizeInBytes ;
261+ }
262+
243263 /**
244264 * This configures the maximum script compilations per five minute window.
245265 *
@@ -303,6 +323,13 @@ public <FactoryType> FactoryType compile(Script script, ScriptContext<FactoryTyp
303323 throw new IllegalArgumentException ("cannot execute scripts using [" + context .name + "] context" );
304324 }
305325
326+ if (type == ScriptType .INLINE ) {
327+ if (idOrCode .getBytes (StandardCharsets .UTF_8 ).length > maxSizeInBytes ) {
328+ throw new IllegalArgumentException ("exceeded max allowed inline script size in bytes [" + maxSizeInBytes + "] " +
329+ "with size [" + idOrCode .getBytes (StandardCharsets .UTF_8 ).length + "] for script [" + idOrCode + "]" );
330+ }
331+ }
332+
306333 if (logger .isTraceEnabled ()) {
307334 logger .trace ("compiling lang: [{}] type: [{}] script: {}" , lang , type , idOrCode );
308335 }
@@ -397,6 +424,20 @@ public boolean isAnyContextEnabled() {
397424 return contextsAllowed == null || contextsAllowed .isEmpty () == false ;
398425 }
399426
427+ Map <String , StoredScriptSource > getScriptsFromClusterState () {
428+ if (clusterState == null ) {
429+ return Collections .emptyMap ();
430+ }
431+
432+ ScriptMetaData scriptMetadata = clusterState .metaData ().custom (ScriptMetaData .TYPE );
433+
434+ if (scriptMetadata == null ) {
435+ return Collections .emptyMap ();
436+ }
437+
438+ return scriptMetadata .getStoredScripts ();
439+ }
440+
400441 StoredScriptSource getScriptFromClusterState (String id ) {
401442 ScriptMetaData scriptMetadata = clusterState .metaData ().custom (ScriptMetaData .TYPE );
402443
@@ -415,10 +456,8 @@ StoredScriptSource getScriptFromClusterState(String id) {
415456
416457 public void putStoredScript (ClusterService clusterService , PutStoredScriptRequest request ,
417458 ActionListener <AcknowledgedResponse > listener ) {
418- int max = SCRIPT_MAX_SIZE_IN_BYTES .get (settings );
419-
420- if (request .content ().length () > max ) {
421- throw new IllegalArgumentException ("exceeded max allowed stored script size in bytes [" + max + "] with size [" +
459+ if (request .content ().length () > maxSizeInBytes ) {
460+ throw new IllegalArgumentException ("exceeded max allowed stored script size in bytes [" + maxSizeInBytes + "] with size [" +
422461 request .content ().length () + "] for script [" + request .id () + "]" );
423462 }
424463
0 commit comments