From 08a315fc7f49a8bd53c9e9e09666affbb9a05495 Mon Sep 17 00:00:00 2001 From: Jeff Boulter Date: Wed, 21 Feb 2024 14:41:56 -0500 Subject: [PATCH 1/2] limit length of strings in operators --- .../jinjava/el/ext/AdditionOperator.java | 16 ++++----- .../el/ext/StringBuildingOperator.java | 16 +++++++++ .../jinjava/el/ext/StringConcatOperator.java | 6 ++-- .../jinjava/el/ExtendedSyntaxBuilderTest.java | 27 ++++++++++++++- .../jinjava/el/ext/AdditionOperatorTest.java | 33 ++++++++++++++++++- 5 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/hubspot/jinjava/el/ext/StringBuildingOperator.java diff --git a/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java b/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java index 4dff03e5b..f3d90e326 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java @@ -3,14 +3,11 @@ import de.odysseus.el.misc.NumberOperations; import de.odysseus.el.misc.TypeConverter; import de.odysseus.el.tree.impl.ast.AstBinary; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; -public class AdditionOperator extends AstBinary.SimpleOperator { +public class AdditionOperator + extends AstBinary.SimpleOperator + implements StringBuildingOperator { @SuppressWarnings("unchecked") @Override @@ -33,7 +30,10 @@ protected Object apply(TypeConverter converter, Object o1, Object o2) { } if (o1 instanceof String || o2 instanceof String) { - return Objects.toString(o1).concat(Objects.toString(o2)); + return getStringBuilder() + .append(Objects.toString(o1)) + .append(Objects.toString(o2)) + .toString(); } return NumberOperations.add(converter, o1, o2); diff --git a/src/main/java/com/hubspot/jinjava/el/ext/StringBuildingOperator.java b/src/main/java/com/hubspot/jinjava/el/ext/StringBuildingOperator.java new file mode 100644 index 000000000..47296089f --- /dev/null +++ b/src/main/java/com/hubspot/jinjava/el/ext/StringBuildingOperator.java @@ -0,0 +1,16 @@ +package com.hubspot.jinjava.el.ext; + +import com.hubspot.jinjava.interpret.JinjavaInterpreter; +import com.hubspot.jinjava.util.LengthLimitingStringBuilder; + +public interface StringBuildingOperator { + default LengthLimitingStringBuilder getStringBuilder() { + JinjavaInterpreter interpreter = JinjavaInterpreter.getCurrent(); + + long maxSize = (interpreter == null || interpreter.getConfig() == null) + ? 0 + : interpreter.getConfig().getMaxOutputSize(); + + return new LengthLimitingStringBuilder(maxSize); + } +} diff --git a/src/main/java/com/hubspot/jinjava/el/ext/StringConcatOperator.java b/src/main/java/com/hubspot/jinjava/el/ext/StringConcatOperator.java index 4e78a3f50..16ddc66bc 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/StringConcatOperator.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/StringConcatOperator.java @@ -9,14 +9,16 @@ import de.odysseus.el.tree.impl.ast.AstBinary.SimpleOperator; import de.odysseus.el.tree.impl.ast.AstNode; -public class StringConcatOperator extends SimpleOperator { +public class StringConcatOperator + extends SimpleOperator + implements StringBuildingOperator { @Override protected Object apply(TypeConverter converter, Object o1, Object o2) { String o1s = converter.convert(o1, String.class); String o2s = converter.convert(o2, String.class); - return new StringBuilder(o1s).append(o2s).toString(); + return getStringBuilder().append(o1s).append(o2s).toString(); } @Override diff --git a/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java b/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java index c3e9d49fe..915511c53 100644 --- a/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java +++ b/src/test/java/com/hubspot/jinjava/el/ExtendedSyntaxBuilderTest.java @@ -6,8 +6,10 @@ import com.google.common.collect.Lists; import com.google.common.io.Resources; import com.hubspot.jinjava.Jinjava; +import com.hubspot.jinjava.JinjavaConfig; import com.hubspot.jinjava.interpret.Context; import com.hubspot.jinjava.interpret.JinjavaInterpreter; +import com.hubspot.jinjava.interpret.OutputTooBigException; import com.hubspot.jinjava.interpret.TemplateError.ErrorReason; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -21,12 +23,16 @@ @SuppressWarnings("unchecked") public class ExtendedSyntaxBuilderTest { + private static final long MAX_STRING_LENGTH = 10_000; + private Context context; private JinjavaInterpreter interpreter; @Before public void setup() { - interpreter = new Jinjava().newInterpreter(); + interpreter = + new Jinjava(JinjavaConfig.newBuilder().withMaxOutputSize(MAX_STRING_LENGTH).build()) + .newInterpreter(); JinjavaInterpreter.pushCurrent(interpreter); context = interpreter.getContext(); @@ -96,6 +102,25 @@ public void stringConcatOperator() { assertThat(val("'foo' ~ 'bar'")).isEqualTo("foobar"); } + @Test + public void itLimitsLengthInStringConcatOperator() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < MAX_STRING_LENGTH - 1; i++) { + stringBuilder.append("0"); + } + + String longString = stringBuilder.toString(); + + context.put("longString", longString); + assertThat(val("longString ~ ''")).isEqualTo(longString); + assertThat(interpreter.getErrors()).isEmpty(); + + assertThat(val("longString ~ 'OVER'")).isNull(); + + assertThat(interpreter.getErrors().get(0).getMessage()) + .contains(OutputTooBigException.class.getSimpleName()); + } + @Test public void stringInStringOperator() { assertThat(val("'foo' in 'foobar'")).isEqualTo(true); diff --git a/src/test/java/com/hubspot/jinjava/el/ext/AdditionOperatorTest.java b/src/test/java/com/hubspot/jinjava/el/ext/AdditionOperatorTest.java index 5c7f3165d..97ae7f0b1 100644 --- a/src/test/java/com/hubspot/jinjava/el/ext/AdditionOperatorTest.java +++ b/src/test/java/com/hubspot/jinjava/el/ext/AdditionOperatorTest.java @@ -4,20 +4,32 @@ import static org.assertj.core.api.Assertions.entry; import com.hubspot.jinjava.Jinjava; +import com.hubspot.jinjava.JinjavaConfig; import com.hubspot.jinjava.interpret.JinjavaInterpreter; +import com.hubspot.jinjava.interpret.OutputTooBigException; import java.util.Collection; import java.util.Map; +import org.junit.After; import org.junit.Before; import org.junit.Test; @SuppressWarnings("unchecked") public class AdditionOperatorTest { + private static final long MAX_STRING_LENGTH = 10_000; private JinjavaInterpreter interpreter; @Before public void setup() { - interpreter = new Jinjava().newInterpreter(); + interpreter = + new Jinjava(JinjavaConfig.newBuilder().withMaxOutputSize(MAX_STRING_LENGTH).build()) + .newInterpreter(); + JinjavaInterpreter.pushCurrent(interpreter); + } + + @After + public void teardown() { + JinjavaInterpreter.popCurrent(); } @Test @@ -25,6 +37,25 @@ public void itConcatsStrings() { assertThat(interpreter.resolveELExpression("'foo' + 'bar'", -1)).isEqualTo("foobar"); } + @Test + public void itLimitsLengthOfStrings() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < MAX_STRING_LENGTH; i++) { + stringBuilder.append("0"); + } + + String first = stringBuilder.toString(); + assertThat(interpreter.resolveELExpression("'" + first + "' + ''", -1)) + .isEqualTo(first); + assertThat(interpreter.getErrors()).isEmpty(); + + assertThat(interpreter.resolveELExpression("'" + first + "' + 'TOOBIG'", -1)) + .isNull(); + + assertThat(interpreter.getErrors().get(0).getMessage()) + .contains(OutputTooBigException.class.getSimpleName()); + } + @Test public void itAddsNumbers() { assertThat(interpreter.resolveELExpression("1 + 2", -1)).isEqualTo(3L); From 9621f673e0ec0263a6d3366748dea110af098d23 Mon Sep 17 00:00:00 2001 From: Jeff Boulter Date: Wed, 21 Feb 2024 14:42:47 -0500 Subject: [PATCH 2/2] explicit imports --- .../java/com/hubspot/jinjava/el/ext/AdditionOperator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java b/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java index f3d90e326..b9f6a99b6 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/AdditionOperator.java @@ -3,7 +3,12 @@ import de.odysseus.el.misc.NumberOperations; import de.odysseus.el.misc.TypeConverter; import de.odysseus.el.tree.impl.ast.AstBinary; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; public class AdditionOperator extends AstBinary.SimpleOperator