diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java index a5f476fec..92193cbc4 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java @@ -19,6 +19,7 @@ package com.opensymphony.xwork2.ognl; import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.XWorkConstants; import com.opensymphony.xwork2.TextProvider; import com.opensymphony.xwork2.conversion.NullHandler; import com.opensymphony.xwork2.conversion.impl.XWorkConverter; @@ -61,7 +62,7 @@ public class OgnlValueStackFactory implements ValueStackFactory { this.textProvider = textProvider; } - @Inject(value="allowStaticMethodAccess", required=false) + @Inject(value = XWorkConstants.ALLOW_STATIC_METHOD_ACCESS, required = false) protected void setAllowStaticMethodAccess(String allowStaticMethodAccess) { this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess); } diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java index 4e1e964eb..0e32efd93 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java @@ -49,7 +49,7 @@ public class SecurityMemberAccess extends DefaultMemberAccess { /** * SecurityMemberAccess * - access decisions based on whether member is static (or not) - * - block or allow access to properties (configureable-after-construction) + * - block or allow access to properties (configurable-after-construction) * * @param allowStaticMethodAccess */ diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java index 0f9ec65a2..9b0e7d4ea 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java @@ -82,13 +82,14 @@ public class ProxyUtil { } /** - * Check whether the given member is a proxy member of a proxy object. + * Check whether the given member is a proxy member of a proxy object or is a static proxy member. * @param member the member to check * @param object the object to check */ public static boolean isProxyMember(Member member, Object object) { - if (!isProxy(object)) + if (!Modifier.isStatic(member.getModifiers()) && !isProxy(object)) { return false; + } Boolean flag = isProxyMemberCache.get(member); if (flag != null) { diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java index c32e85878..f8669ba22 100644 --- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java @@ -39,7 +39,17 @@ import java.util.*; import java.util.regex.Pattern; public class OgnlUtilTest extends XWorkTestCase { - + + // Fields for static field access test + public static final String STATIC_FINAL_PUBLIC_ATTRIBUTE = "Static_Final_Public_Attribute"; + static final String STATIC_FINAL_PACKAGE_ATTRIBUTE = "Static_Final_Package_Attribute"; + protected static final String STATIC_FINAL_PROTECTED_ATTRIBUTE = "Static_Final_Protected_Attribute"; + private static final String STATIC_FINAL_PRIVATE_ATTRIBUTE = "Static_Final_Private_Attribute"; + public static String STATIC_PUBLIC_ATTRIBUTE = "Static_Public_Attribute"; + static String STATIC_PACKAGE_ATTRIBUTE = "Static_Package_Attribute"; + protected static String STATIC_PROTECTED_ATTRIBUTE = "Static_Protected_Attribute"; + private static String STATIC_PRIVATE_ATTRIBUTE = "Static_Private_Attribute"; + private OgnlUtil ognlUtil; @Override @@ -1024,6 +1034,124 @@ public class OgnlUtilTest extends XWorkTestCase { assertTrue("fakepackage4.package not in exclusions?", excludedPackageNames.contains("fakepackage4.package")); } + /** + * Ensure getValue permits public static field access, but prevents non-public static field access + */ + public void testStaticFieldGetValue() { + OgnlContext context = null; + Object accessedValue; + + try { + reloadTestContainerConfiguration(false, false); // Test with allow static methods false + context = (OgnlContext) ognlUtil.createDefaultContext(null); + } catch (Exception ex) { + fail("unable to reload test configuration? Exception: " + ex); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, null); + assertEquals("accessed field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE); + } catch (Exception ex) { + fail("static final public field access failed ? Exception: " + ex); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PUBLIC_ATTRIBUTE", context, null); + assertEquals("accessed field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE); + } catch (Exception ex) { + fail("static public field access failed ? Exception: " + ex); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null); + fail("static final package field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null); + fail("static package field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null); + fail("static final protected field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null); + fail("static protected field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null); + fail("static final private field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null); + fail("static private field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + + try { + reloadTestContainerConfiguration(false, true); // Re-test with allow static methods true + context = (OgnlContext) ognlUtil.createDefaultContext(null); + } catch (Exception ex) { + fail("unable to reload test configuration? Exception: " + ex); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, null); + assertEquals("accessed value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE); + } catch (Exception ex) { + fail("static final public field access failed ? Exception: " + ex); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PUBLIC_ATTRIBUTE", context, null); + assertEquals("accessed value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE); + } catch (Exception ex) { + fail("static public field access failed ? Exception: " + ex); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PACKAGE_ATTRIBUTE", context, null); + fail("static final package field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PACKAGE_ATTRIBUTE", context, null); + fail("static package field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PROTECTED_ATTRIBUTE", context, null); + fail("static final protected field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PROTECTED_ATTRIBUTE", context, null); + fail("static protected field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PRIVATE_ATTRIBUTE", context, null); + fail("static final private field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + try { + accessedValue = ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, null); + fail("static private field access succeeded?"); + } catch (Exception ex) { + assertTrue("Exception not an OgnlException?", ex instanceof OgnlException); + } + } + private void internalTestInitialEmptyOgnlUtilExclusions(OgnlUtil ognlUtilParam) throws Exception { Set> excludedClasses = ognlUtilParam.getExcludedClasses(); assertNotNull("parameter (default) exluded classes null?", excludedClasses); diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-false.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-false.xml index 132870dd9..1f0c0ee90 100644 --- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-false.xml +++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-false.xml @@ -33,6 +33,7 @@ + diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-true.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-true.xml index 3065a1ade..7551cb10d 100644 --- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-true.xml +++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-devmode-true.xml @@ -33,6 +33,7 @@ + diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-true.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-true.xml index 6dc36eb3c..220432cae 100644 --- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-true.xml +++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowstatic-true.xml @@ -33,6 +33,7 @@ + diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-devmode-true.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-devmode-true.xml index 787d8a632..59914b6c4 100644 --- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-devmode-true.xml +++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-devmode-true.xml @@ -33,6 +33,7 @@ + diff --git a/pom.xml b/pom.xml index bfe7ac49f..1c6ce69a5 100644 --- a/pom.xml +++ b/pom.xml @@ -98,12 +98,12 @@ UTF-8 4.3.20.RELEASE - 3.1.21 + 3.1.22 7.0 3.0.8 1.0.7 2.11.1 - 2.9.7 + 2.9.8 1.7