You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2021/06/02 14:42:29 UTC

[commons-jexl] branch master updated: JEXL-336: fixed/reverted behavior of constant template that should not interpret escape characters

This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c385e3  JEXL-336: fixed/reverted behavior of constant template that should not interpret escape characters
8c385e3 is described below

commit 8c385e3dee534fc497644dc1e8403cb42c668ee7
Author: henrib <he...@apache.org>
AuthorDate: Wed Jun 2 16:42:19 2021 +0200

    JEXL-336: fixed/reverted behavior of constant template that should not interpret escape characters
---
 .../commons/jexl3/internal/TemplateEngine.java     |  2 +-
 .../apache/commons/jexl3/parser/StringParser.java  | 63 +++++++++++++++++-----
 .../java/org/apache/commons/jexl3/JXLTTest.java    | 19 +++++++
 3 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java b/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
index d070fd2..af068fa 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
@@ -388,7 +388,7 @@ public final class TemplateEngine extends JxltEngine {
                 throw new NullPointerException("constant can not be null");
             }
             if (val instanceof String) {
-                val = StringParser.buildString((String) val, false);
+                val = StringParser.buildTemplate((String) val, false);
             }
             this.value = val;
         }
diff --git a/src/main/java/org/apache/commons/jexl3/parser/StringParser.java b/src/main/java/org/apache/commons/jexl3/parser/StringParser.java
index 0754896..f3f15ae 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/StringParser.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/StringParser.java
@@ -45,11 +45,32 @@ public class StringParser {
      * @return the built string
      */
     public static String buildString(final CharSequence str, final boolean eatsep) {
+        return buildString(str, eatsep, true);
+    }
+
+    /**
+     * Builds a template, does not escape characters.
+     * @param str the string to build from
+     * @param eatsep whether the separator, the first character, should be considered
+     * @return the built string
+     */
+    public static String buildTemplate(final CharSequence str, final boolean eatsep) {
+        return buildString(str, eatsep, false);
+    }
+
+    /**
+     * Builds a string, handles escaping through '\' syntax.
+     * @param str the string to build from
+     * @param eatsep whether the separator, the first character, should be considered
+     * @param esc whether escape characters are interpreted or escaped
+     * @return the built string
+     */
+    private static String buildString(final CharSequence str, final boolean eatsep, final boolean esc) {
         final StringBuilder strb = new StringBuilder(str.length());
         final char sep = eatsep ? str.charAt(0) : 0;
         final int end = str.length() - (eatsep ? 1 : 0);
         final int begin = (eatsep ? 1 : 0);
-        read(strb, str, begin, end, sep);
+        read(strb, str, begin, end, sep, esc);
         return strb.toString();
     }
 
@@ -72,7 +93,7 @@ public class StringParser {
      * @return the offset in origin
      */
     public static int readString(final StringBuilder strb, final CharSequence str, final int index, final char sep) {
-        return read(strb, str, index, str.length(), sep);
+        return read(strb, str, index, str.length(), sep, true);
     }
     /** The length of an escaped unicode sequence. */
     private static final int UCHAR_LEN = 4;
@@ -85,9 +106,10 @@ public class StringParser {
      * @param begin the relative offset in str to begin reading
      * @param end the relative offset in str to end reading
      * @param sep the separator, single or double quote, marking end of string
+     * @param esc whether escape characters are interpreted or escaped
      * @return the last character offset handled in origin
      */
-    private static int read(final StringBuilder strb, final CharSequence str, final int begin, final int end, final char sep) {
+    private static int read(final StringBuilder strb, final CharSequence str, final int begin, final int end, final char sep, final boolean esc) {
         boolean escape = false;
         int index = begin;
         for (; index < end; ++index) {
@@ -99,15 +121,30 @@ public class StringParser {
                     // if c is not an escapable character, re-emmit the backslash before it
                     final boolean notSeparator = sep == 0 ? c != '\'' && c != '"' : c != sep;
                     if (notSeparator && c != '\\') {
-                        switch (c) {
-                            // http://es5.github.io/x7.html#x7.8.4
-                            case 'b': strb.append('\b'); break; // backspace \u0008
-                            case 't': strb.append('\t'); break; // horizontal tab \u0009
-                            case 'n': strb.append('\n'); break; // line feed \u000A
-                            // We don't support vertical tab. If needed, the unicode (\u000B) should be used instead
-                            case 'f': strb.append('\f'); break; // form feed \u000C
-                            case 'r': strb.append('\r'); break; // carriage return \u000D
-                            default: strb.append('\\').append(c);
+                        if (!esc) {
+                            strb.append('\\').append(c);
+                        } else {
+                            switch (c) {
+                                // http://es5.github.io/x7.html#x7.8.4
+                                case 'b':
+                                    strb.append('\b');
+                                    break; // backspace \u0008
+                                case 't':
+                                    strb.append('\t');
+                                    break; // horizontal tab \u0009
+                                case 'n':
+                                    strb.append('\n');
+                                    break; // line feed \u000A
+                                // We don't support vertical tab. If needed, the unicode (\u000B) should be used instead
+                                case 'f':
+                                    strb.append('\f');
+                                    break; // form feed \u000C
+                                case 'r':
+                                    strb.append('\r');
+                                    break; // carriage return \u000D
+                                default:
+                                    strb.append('\\').append(c);
+                            }
                         }
                     } else {
                         strb.append(c);
@@ -287,4 +324,4 @@ public class StringParser {
         }
         return strb == null ? str : strb.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/java/org/apache/commons/jexl3/JXLTTest.java b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
index b6c032b..8e4de30 100644
--- a/src/test/java/org/apache/commons/jexl3/JXLTTest.java
+++ b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
@@ -1161,4 +1161,23 @@ public class JXLTTest extends JexlTestCase {
         Assert.assertEquals("42\n", strw.toString());
     }
 
+    @Test
+    public void testConstantTemplate() {
+        String src = "<script>\n" +
+                "      function test(src){\n" +
+                "        var res = src.replace(/\\n\\t\\s/g, '\\n');\n" +
+                "      }\n" +
+                "      test();\n" +
+                "    </script>";
+        final JexlContext ctxt = new MapContext();
+        final JexlEngine jexl = new JexlBuilder().create();
+        final JxltEngine jxlt = jexl.createJxltEngine();
+        JxltEngine.Template tmplt;
+        tmplt = jxlt.createTemplate(src);
+        Assert.assertNotNull(tmplt);
+        final Writer strw = new StringWriter();
+        tmplt.evaluate(ctxt, strw);
+        String result = strw.toString();
+        Assert.assertEquals(src, result);
+    }
 }