WW-4062 Cache OgnlException thrown on compilation

This commit is contained in:
Kusal Kithul-Godage
2024-08-09 19:53:59 +10:00
parent a4464099d9
commit 6caa932fff
2 changed files with 31 additions and 1 deletions
@@ -601,12 +601,27 @@ public class OgnlUtil {
if (enableExpressionCache) {
tree = expressionCache.get(expr);
}
if (tree instanceof OgnlException) {
// OgnlException was cached, rethrow it with updated stack trace
OgnlException e = (OgnlException) tree;
e.getCause().fillInStackTrace();
throw e;
}
if (tree == null) {
tree = ognlGuard.parseExpression(expr);
try {
tree = ognlGuard.parseExpression(expr);
} catch (OgnlException e) {
tree = e;
}
if (enableExpressionCache) {
expressionCache.put(expr, tree);
}
if (tree instanceof OgnlException) {
// Rethrow OgnlException after caching
throw (OgnlException) tree;
}
}
if (EXPR_BLOCKED.equals(tree)) {
throw new OgnlException("Expression blocked by OgnlGuard: " + expr);
}
@@ -1645,6 +1645,21 @@ public class OgnlUtilTest extends XWorkTestCase {
assertThrows(OgnlException.class, () -> ognlUtil.getValue(vulnerableExpr, ognlUtil.createDefaultContext(null), null));
}
public void testCompilationErrorsCached() throws Exception {
OgnlException e = assertThrows(OgnlException.class, () -> ognlUtil.compile(".literal.$something"));
StackTraceElement[] stackTrace = e.getStackTrace();
assertThat(stackTrace).isEmpty();
StackTraceElement[] causeStackTrace = e.getCause().getStackTrace();
OgnlException e2 = assertThrows(OgnlException.class, () -> ognlUtil.compile(".literal.$something"));
StackTraceElement[] stackTrace2 = e.getStackTrace();
assertThat(stackTrace2).isEmpty();
StackTraceElement[] causeStackTrace2 = e.getCause().getStackTrace();
assertSame(e, e2); // Exception is cached
assertThat(causeStackTrace).isNotEqualTo(causeStackTrace2); // Stack trace refreshed
}
/**
* Generate a new OgnlUtil instance (not configured by the {@link ContainerBuilder}) that can be used for
* basic tests, with its Expression and BeanInfo factories set to LRU mode.