Skip to content

Commit

Permalink
Add a size limit to outputs from mustache
Browse files Browse the repository at this point in the history
  • Loading branch information
thecoop committed Oct 3, 2024
1 parent 87deb99 commit 1ccee3f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.text.SizeLimitingStringWriter;
import org.elasticsearch.script.GeneralScriptException;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
Expand Down Expand Up @@ -47,6 +49,8 @@ public final class MustacheScriptEngine implements ScriptEngine {

public static final String NAME = "mustache";

private static final int MUSTACHE_SIZE_LIMIT = 1024 * 1024 * 1024; // 1GB

/**
* Compile a template string to (in this case) a Mustache object than can
* later be re-used for execution to fill in missing parameter values.
Expand Down Expand Up @@ -118,20 +122,25 @@ private class MustacheExecutableScript extends TemplateScript {

@Override
public String execute() {
final StringWriter writer = new StringWriter();
StringWriter writer = new SizeLimitingStringWriter(MUSTACHE_SIZE_LIMIT);
try {
template.execute(writer, params);
} catch (Exception e) {
if (shouldLogException(e)) {
logger.error(() -> format("Error running %s", template), e);
}
if (e.getCause() instanceof SizeLimitingStringWriter.SizeLimitExceededException) {
throw new ElasticsearchParseException("Script string size exceeded", e);
}
throw new GeneralScriptException("Error running " + template, e);
}
return writer.toString();
}

public boolean shouldLogException(Throwable e) {
return e.getCause() != null && e.getCause() instanceof MustacheInvalidParameterException == false;
return e.getCause() != null
&& e.getCause() instanceof MustacheInvalidParameterException == false
&& e.getCause() instanceof SizeLimitingStringWriter.SizeLimitExceededException == false;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.common.text;

import org.elasticsearch.common.Strings;

import java.io.StringWriter;

public class SizeLimitingStringWriter extends StringWriter {

public static class SizeLimitExceededException extends IllegalStateException {
public SizeLimitExceededException(String message) {
super(message);
}
}

private final int sizeLimit;

public SizeLimitingStringWriter(int sizeLimit) {
this.sizeLimit = sizeLimit;
}

private void checkSizeLimit(int additionalChars) {
if (getBuffer().length() + additionalChars >= sizeLimit) {
throw new SizeLimitExceededException(
Strings.format("String [%s...] has exceeded the size limit [%s]", getBuffer().substring(0, 20), sizeLimit)
);
}
}

@Override
public void write(int c) {
checkSizeLimit(1);
super.write(c);
}

// write(char[]) delegates to write(char[], int, int)

@Override
public void write(char[] cbuf, int off, int len) {
checkSizeLimit(len);
super.write(cbuf, off, len);
}

@Override
public void write(String str) {
checkSizeLimit(str.length());
super.write(str);
}

@Override
public void write(String str, int off, int len) {
checkSizeLimit(len);
super.write(str, off, len);
}

// append(...) delegates to write(...) methods
}

0 comments on commit 1ccee3f

Please sign in to comment.