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 2020/01/27 18:41:34 UTC

[commons-jexl] 01/02: JEXL-322: read through strings when parsing template exrepssions Task #JEXL-322 - JXLT String literals cannot contain curly braces

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

commit fc4b5a4d52c68c6f788526983a6df5bdd4f972b0
Author: henrib <he...@apache.org>
AuthorDate: Mon Jan 27 19:40:02 2020 +0100

    JEXL-322: read through strings when parsing template exrepssions
    Task #JEXL-322 - JXLT String literals cannot contain curly braces
---
 .../commons/jexl3/internal/TemplateEngine.java     | 41 +++++++++++++++++++---
 .../org/apache/commons/jexl3/Issues300Test.java    | 34 ++++++++++++++++++
 2 files changed, 70 insertions(+), 5 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 449848d..056c2cc 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
@@ -722,6 +722,37 @@ public final class TemplateEngine extends JxltEngine {
     }
 
     /**
+     * Helper for expression dealing with embedded strings.
+     * @param strb the expression buffer to copy characters into
+     * @param expr the source
+     * @param position the offset into the source
+     * @param c the separator character
+     * @return the new position to read the source from 
+     */
+    private static int append(StringBuilder strb, CharSequence expr, int position, char c) {
+        strb.append(c);
+        if (c != '"' && c != '\'') {
+            return position;
+        } 
+        // read thru strings
+        int end = expr.length();
+        boolean escape= false;
+        int index = position + 1;
+        for (; index < end; ++index) {
+            char ec = expr.charAt(index);
+            strb.append(ec);
+            if (ec == '\\') {
+                escape = !escape;
+            } else if (escape) {
+                escape = false;
+            } else if (ec == c) {
+                break;
+            }
+        }
+        return index;
+    }
+    
+    /**
      * Parses a unified expression.
      * @param info  the source info
      * @param expr  the string expression
@@ -755,7 +786,7 @@ public final class TemplateEngine extends JxltEngine {
                         state = ParseState.ESCAPE;
                     } else {
                         // do buildup expr
-                        strb.append(c);
+                        column = append(strb, expr, column, c);
                     }
                     break;
                 case IMMEDIATE0: // $
@@ -770,7 +801,7 @@ public final class TemplateEngine extends JxltEngine {
                     } else {
                         // revert to CONST
                         strb.append(immediateChar);
-                        strb.append(c);
+                        column = append(strb, expr, column, c);
                         state = ParseState.CONST;
                     }
                     break;
@@ -786,7 +817,7 @@ public final class TemplateEngine extends JxltEngine {
                     } else {
                         // revert to CONST
                         strb.append(deferredChar);
-                        strb.append(c);
+                        column = append(strb, expr, column, c);
                         state = ParseState.CONST;
                     }
                     break;
@@ -811,7 +842,7 @@ public final class TemplateEngine extends JxltEngine {
                             immediate1 += 1;
                         }
                         // do buildup expr
-                        strb.append(c);
+                        column = append(strb, expr, column, c);
                     }
                     break;
                 case DEFERRED1: // #{...
@@ -863,7 +894,7 @@ public final class TemplateEngine extends JxltEngine {
                         }
                     } else {
                         // do buildup expr
-                        strb.append(c);
+                        column = append(strb, expr, column, c);
                     }
                     break;
                 case ESCAPE:
diff --git a/src/test/java/org/apache/commons/jexl3/Issues300Test.java b/src/test/java/org/apache/commons/jexl3/Issues300Test.java
index 913133b..6649f3a 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues300Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues300Test.java
@@ -16,6 +16,8 @@
  */
 package org.apache.commons.jexl3;
 
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -344,4 +346,36 @@ public class Issues300Test {
         result = script.execute(ctxt, 21);
         Assert.assertEquals(42, result);
     }
+
+    @Test
+    public void test322() throws Exception {
+        JexlEngine jexl = new JexlBuilder().strict(true).create();
+        JxltEngine jxlt = jexl.createJxltEngine();
+        JexlContext context = new MapContext();
+
+        String[] ins = new String[]{
+            "${'{'}", "${\"{\"}", "${\"{}\"}", "${'{42}'}", "${\"{\\\"\\\"}\"}"
+        };
+        String[] ctls = new String[]{
+            "{", "{", "{}", "{42}", "{\"\"}"
+        };
+        StringWriter strw;
+        JxltEngine.Template template;
+        String output;
+
+        for (int i = 0; i < ins.length; ++i) {
+            String src = ins[i];
+            try {
+                template = jxlt.createTemplate("$$", new StringReader(src));
+            } catch(JexlException xany) {
+                Assert.fail(src);
+                throw xany;
+            }
+            strw = new StringWriter();
+            template.evaluate(context, strw);
+            output = strw.toString();
+            Assert.assertEquals(ctls[i], output);
+        }
+    }
+
 }