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

kusal pushed a commit to branch WW-5340-ognl-guard
in repository https://gitbox.apache.org/repos/asf/struts.git


The following commit(s) were added to refs/heads/WW-5340-ognl-guard by this 
push:
     new 02db3683b WW-5340 Refactor OgnlGuard to do the parsing
02db3683b is described below

commit 02db3683bdd201737b78ad3fac55b81c0b3cded5
Author: Kusal Kithul-Godage <g...@kusal.io>
AuthorDate: Fri Sep 1 00:16:34 2023 +1000

    WW-5340 Refactor OgnlGuard to do the parsing
---
 .../opensymphony/xwork2/ognl/DefaultOgnlGuard.java |  7 +++-
 .../com/opensymphony/xwork2/ognl/OgnlGuard.java    | 48 ++++++++++++++++++++--
 .../com/opensymphony/xwork2/ognl/OgnlUtil.java     |  7 +---
 .../xwork2/ognl/DefaultOgnlGuardTest.java          | 18 +++-----
 4 files changed, 59 insertions(+), 21 deletions(-)

diff --git 
a/core/src/main/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuard.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuard.java
index 4e45a19ad..55a5d8f74 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuard.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuard.java
@@ -65,7 +65,12 @@ public class DefaultOgnlGuard implements OgnlGuard {
     }
 
     @Override
-    public boolean isBlocked(String expr, Object tree) {
+    public boolean isRawExpressionBlocked(String expr) {
+        return false;
+    }
+
+    @Override
+    public boolean isParsedTreeBlocked(Object tree) {
         return containsExcludedNodeType(tree);
     }
 
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlGuard.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlGuard.java
index b1bcb409e..b0e75f4c1 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlGuard.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlGuard.java
@@ -18,6 +18,9 @@
  */
 package com.opensymphony.xwork2.ognl;
 
+import ognl.Ognl;
+import ognl.OgnlException;
+
 /**
  * Guards all expressions parsed by Struts Core. It is evaluated by {@link 
OgnlUtil} immediately after parsing any
  * expression.
@@ -26,12 +29,51 @@ package com.opensymphony.xwork2.ognl;
  */
 public interface OgnlGuard {
 
+    String GUARD_BLOCKED = "_ognl_guard_blocked";
+
     /**
-     * It is imperative that the parsed tree matches the expression.
+     * Determines whether an OGNL expression should be blocked based on 
validation done on both the raw expression and
+     * the parsed tree.
      *
      * @param expr OGNL expression
-     * @param tree parsed tree of expression
      * @return whether the expression should be blocked
      */
-    boolean isBlocked(String expr, Object tree);
+    default boolean isBlocked(String expr) throws OgnlException {
+        return GUARD_BLOCKED.equals(parseExpression(expr));
+    }
+
+    /**
+     * Parses an OGNL expression and returns the resulting tree only if the 
expression is not blocked as per defined
+     * validation rules in {@link #isRawExpressionBlocked} and {@link 
#isParsedTreeBlocked}.
+     *
+     * @param expr OGNL expression
+     * @return parsed expression or {@link #GUARD_BLOCKED} if the expression 
should be blocked
+     */
+    default Object parseExpression(String expr) throws OgnlException {
+        if (isRawExpressionBlocked(expr)) {
+            return GUARD_BLOCKED;
+        }
+        Object tree = Ognl.parseExpression(expr);
+        if (isParsedTreeBlocked(tree)) {
+            return GUARD_BLOCKED;
+        }
+        return expr;
+    }
+
+    /**
+     * Determines whether an OGNL expression should be blocked based on 
validation done on only the raw expression,
+     * without parsing the tree.
+     *
+     * @param expr OGNL expression
+     * @return whether the expression should be blocked
+     */
+    boolean isRawExpressionBlocked(String expr);
+
+    /**
+     * Determines whether a parsed OGNL tree should be blocked based on some 
validation rules.
+     *
+     * @param tree parsed OGNL tree
+     * @return whether the parsed tree should be blocked
+     */
+    boolean isParsedTreeBlocked(Object tree);
 }
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
index 8a276435a..8f207541f 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -52,6 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
+import static com.opensymphony.xwork2.ognl.OgnlGuard.GUARD_BLOCKED;
 import static 
com.opensymphony.xwork2.util.TextParseUtil.commaDelimitedStringToSet;
 import static java.util.Objects.requireNonNull;
 import static java.util.stream.Collectors.toSet;
@@ -71,7 +72,6 @@ public class OgnlUtil {
     // Flag used to reduce flooding logs with WARNs about using DevMode 
excluded packages
     private final AtomicBoolean warnReported = new AtomicBoolean(false);
 
-    private static final String GUARD_BLOCKED = "_ognl_guard_blocked";
     private final OgnlCache<String, Object> expressionCache;
     private final OgnlCache<Class<?>, BeanInfo> beanInfoCache;
     private TypeConverter defaultConverter;
@@ -613,10 +613,7 @@ public class OgnlUtil {
             tree = expressionCache.get(expr);
         }
         if (tree == null) {
-            tree = Ognl.parseExpression(expr);
-            if (ognlGuard.isBlocked(expr, tree)) {
-                tree = GUARD_BLOCKED;
-            }
+            tree = ognlGuard.parseExpression(expr);
             if (enableExpressionCache) {
                 expressionCache.put(expr, tree);
             }
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuardTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuardTest.java
index 793f26432..d04656ddd 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuardTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/DefaultOgnlGuardTest.java
@@ -19,8 +19,6 @@
 package com.opensymphony.xwork2.ognl;
 
 import com.opensymphony.xwork2.config.ConfigurationException;
-import ognl.Ognl;
-import ognl.OgnlException;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -38,19 +36,15 @@ public class DefaultOgnlGuardTest {
         defaultOgnlGuard = new DefaultOgnlGuard();
     }
 
-    private boolean exec(String expr) throws OgnlException {
-        return defaultOgnlGuard.isBlocked(expr, Ognl.parseExpression(expr));
-    }
-
     @Test
     public void notConfigured() throws Exception {
         String expr = "1+1";
-        assertFalse(exec(expr));
+        assertFalse(defaultOgnlGuard.isBlocked(expr));
     }
 
     @Test
     public void nonNodeTree() throws Exception {
-        assertFalse(defaultOgnlGuard.isBlocked("1+1", "String"));
+        assertFalse(defaultOgnlGuard.isParsedTreeBlocked("String"));
     }
 
     @Test
@@ -68,18 +62,18 @@ public class DefaultOgnlGuardTest {
     @Test
     public void addBlocked() throws Exception {
         String expr = "1+1";
-        assertFalse(exec(expr));
+        assertFalse(defaultOgnlGuard.isBlocked(expr));
 
         defaultOgnlGuard.useExcludedNodeTypes("ognl.ASTAdd");
-        assertTrue(exec(expr));
+        assertTrue(defaultOgnlGuard.isBlocked(expr));
     }
 
     @Test
     public void nestedAddBlocked() throws Exception {
         String expr = "{'a',1+1}";
-        assertFalse(exec(expr));
+        assertFalse(defaultOgnlGuard.isBlocked(expr));
 
         defaultOgnlGuard.useExcludedNodeTypes("ognl.ASTAdd");
-        assertTrue(exec(expr));
+        assertTrue(defaultOgnlGuard.isBlocked(expr));
     }
 }

Reply via email to