Commits

mrdon  committed 65e41bf

Fixing recursive parsing of ognl expressions
WW-2030

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/2.0@1544e221344d-f017-0410-9bd5-d282ab1896d7

  • Participants
  • Parent commits 66d6b19
  • Branches 2.0, xwork_2_0_7

Comments (0)

Files changed (2)

File src/java/com/opensymphony/xwork2/util/TextParseUtil.java

  * @version $Date$ $Id$
  */
 public class TextParseUtil {
+    
+    private static final int MAX_RECURSION = 1;
 
     /**
      * Converts all instances of ${...} in <code>expression</code> to the value returned
      * @return Converted object from variable translation.
      */
     public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) {
+        return translateVariables(open, expression, stack, asType, evaluator, MAX_RECURSION);
+    }
+    
+    /**
+     * Converted object from variable translation.
+     *
+     * @param open
+     * @param expression
+     * @param stack
+     * @param asType
+     * @param evaluator
+     * @return Converted object from variable translation.
+     */
+    public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator, int maxLoopCount) {
         // deal with the "pure" expressions first!
         //expression = expression.trim();
         Object result = expression;
-
+        int loopCount = 1;
+        int pos = 0;
         while (true) {
-            int start = expression.indexOf(open + "{");
+            
+            int start = expression.indexOf(open + "{", pos);
+            if (start == -1) {
+                pos = 0;
+                loopCount++;
+                start = expression.indexOf(open + "{");
+            }
+            if (loopCount > maxLoopCount) {
+                // translateVariables prevent infinite loop / expression recursive evaluation
+                break;
+            }
             int length = expression.length();
             int x = start + 2;
             int end;
 
                 String left = expression.substring(0, start);
                 String right = expression.substring(end + 1);
+                String middle = null;
                 if (o != null) {
-                    if (TextUtils.stringSet(left)) {
-                        result = left + o;
-                    } else {
+                    middle = o.toString();
+                    if (!TextUtils.stringSet(left)) {
                         result = o;
+                    } else {
+                        result = left + middle;
                     }
-
+    
                     if (TextUtils.stringSet(right)) {
                         result = result + right;
                     }
 
-                    expression = left + o + right;
+                    expression = left + middle + right;
                 } else {
                     // the variable doesn't exist, so don't display anything
                     result = left + right;
                     expression = left + right;
                 }
+                pos = (left != null && left.length() > 0 ? left.length() - 1: 0) +
+                      (middle != null && middle.length() > 0 ? middle.length() - 1: 0) +
+                      1;
+                pos = Math.max(pos, 1);
             } else {
                 break;
             }

File src/test/com/opensymphony/xwork2/util/TextParseUtilTest.java

 
 import com.opensymphony.xwork2.XWorkTestCase;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.HashSet;
 import java.util.Arrays;
         Object s = TextParseUtil.translateVariables('$', "foo: ${}", stack);
         assertEquals("foo: ", s);
     }
+    
+    public void testTranslateVariablesNoRecursive() {
+        ValueStack stack = ValueStackFactory.getFactory().createValueStack();
+        stack.push(new HashMap() {{ put("foo", "${1+1}"); }});
+
+        Object s = TextParseUtil.translateVariables('$', "foo: ${foo}", stack, String.class, null, 1);
+        assertEquals("foo: ${1+1}", s);
+    }
+    
+    public void testTranslateVariablesRecursive() {
+        ValueStack stack = ValueStackFactory.getFactory().createValueStack();
+        stack.push(new HashMap() {{ put("foo", "${1+1}"); }});
+
+        Object s = TextParseUtil.translateVariables('$', "foo: ${foo}", stack, String.class, null, 2);
+        assertEquals("foo: 2", s);
+    }
 
 }