From 6df80041e32199b5b98099b480af2519e89ff85c Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Tue, 9 Jan 2024 20:54:15 +1100 Subject: [PATCH] WW-5352 Auto allowlist parameterized types! --- apps/showcase/src/main/resources/struts.xml | 5 -- .../parameter/ParametersInterceptor.java | 79 ++++++++++--------- 2 files changed, 41 insertions(+), 43 deletions(-) diff --git a/apps/showcase/src/main/resources/struts.xml b/apps/showcase/src/main/resources/struts.xml index 9f94eec1d..373cf5f7b 100644 --- a/apps/showcase/src/main/resources/struts.xml +++ b/apps/showcase/src/main/resources/struts.xml @@ -36,11 +36,6 @@ - diff --git a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java index 71c84d195..2a500d668 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java @@ -52,6 +52,8 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; @@ -373,61 +375,62 @@ public class ParametersInterceptor extends MethodFilterInterceptor { } protected boolean hasValidAnnotatedPropertyDescriptor(PropertyDescriptor propDesc, long paramDepth) { - Class rootType = getValidAnnotatedPropertyDescriptorType(propDesc, paramDepth); - if (rootType != null) { - if (paramDepth > 0) { - threadAllowlist.allowClass(rootType); - } - return true; - } - return false; - } - - /** - * @return getter return type or setter parameter type, if one corresponding to the paramDepth exists - * with a valid annotation - */ - protected Class getValidAnnotatedPropertyDescriptorType(PropertyDescriptor propDesc, long paramDepth) { Method relevantMethod = paramDepth == 0 ? propDesc.getWriteMethod() : propDesc.getReadMethod(); if (relevantMethod == null) { - return null; + return false; } StrutsParameter annotation = getParameterAnnotation(relevantMethod); - if (annotation != null && annotation.depth() >= paramDepth) { - return paramDepth == 0 ? relevantMethod.getParameterTypes()[0] : relevantMethod.getReturnType(); + if (annotation == null || annotation.depth() < paramDepth) { + return false; + } + if (paramDepth >= 1) { + threadAllowlist.allowClass(relevantMethod.getReturnType()); + } + if (paramDepth >= 2) { + allowlistReturnTypeIfParameterized(relevantMethod); + } + return true; + } + + protected void allowlistReturnTypeIfParameterized(Method method) { + allowlistParameterizedTypeArg(method.getGenericReturnType()); + } + + protected void allowlistParameterizedTypeArg(Type genericType) { + if (!(genericType instanceof ParameterizedType)) { + return; + } + Type paramType = ((ParameterizedType) genericType).getActualTypeArguments()[0]; + if (paramType instanceof Class) { + threadAllowlist.allowClass((Class) paramType); } - return null; } protected boolean hasValidAnnotatedField(Object action, String fieldName, long paramDepth) { - Class rootType = getValidAnnotatedFieldType(action, fieldName, paramDepth); - if (rootType != null) { - if (paramDepth > 0) { - threadAllowlist.allowClass(rootType); - } - return true; - } - return false; - } - - /** - * @return field type if a public field exists on the action with a valid annotation - */ - protected Class getValidAnnotatedFieldType(Object action, String fieldName, long paramDepth) { Field field; try { field = action.getClass().getDeclaredField(fieldName); } catch (NoSuchFieldException e) { - return null; + return false; } if (!Modifier.isPublic(field.getModifiers())) { - return null; + return false; } StrutsParameter annotation = getParameterAnnotation(field); - if (annotation != null && annotation.depth() >= paramDepth) { - return field.getType(); + if (annotation == null || annotation.depth() < paramDepth) { + return false; } - return null; + if (paramDepth >= 1) { + threadAllowlist.allowClass(field.getType()); + } + if (paramDepth >= 2) { + allowlistFieldIfParameterized(field); + } + return true; + } + + protected void allowlistFieldIfParameterized(Field field) { + allowlistParameterizedTypeArg(field.getGenericType()); } /**