This is an automated email from the ASF dual-hosted git repository. kusal pushed a commit to branch WW-5364-populate-allowlist in repository https://gitbox.apache.org/repos/asf/struts.git
commit 33a5b29273156d0f0d104328333059d217a31fd3 Author: Kusal Kithul-Godage <g...@kusal.io> AuthorDate: Thu Nov 23 21:12:15 2023 +1100 WW-5364 Modify XmlDocConfigurationProvider to be able to load into allowlist --- .../providers/XmlDocConfigurationProvider.java | 59 ++++++++++++++++------ 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlDocConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlDocConfigurationProvider.java index 0fcdac0ed..4b9a28297 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlDocConfigurationProvider.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlDocConfigurationProvider.java @@ -45,6 +45,7 @@ import com.opensymphony.xwork2.util.location.LocatableProperties; import com.opensymphony.xwork2.util.location.Location; import com.opensymphony.xwork2.util.location.LocationUtils; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -64,6 +65,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import java.util.stream.Stream; import static com.opensymphony.xwork2.util.TextParseUtil.commaDelimitedStringToSet; import static java.lang.Boolean.parseBoolean; @@ -135,6 +137,16 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid public void destroy() { } + protected Class<?> allowAndLoadClass(String className) throws ClassNotFoundException { + Class<?> clazz = loadClass(className); + List<Class<?>> superClasses = ClassUtils.getAllSuperclasses(clazz); + List<Class<?>> interfaces = ClassUtils.getAllInterfaces(clazz); + Stream.concat(superClasses.stream(), interfaces.stream()).forEach(c -> { + + }); + return clazz; + } + protected Class<?> loadClass(String className) throws ClassNotFoundException { return objectFactory.getClassInstance(className); } @@ -197,7 +209,7 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid String name = child.getAttribute("name"); String impl = child.getAttribute("class"); try { - Class<?> classImpl = loadClass(impl); + Class<?> classImpl = ClassLoaderUtil.loadClass(impl, getClass()); if (BeanSelectionProvider.class.isAssignableFrom(classImpl)) { BeanSelectionProvider provider = (BeanSelectionProvider) classImpl.newInstance(); provider.register(containerBuilder, props); @@ -442,13 +454,8 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid Location location = DomHelper.getLocationObject(actionElement); - if (location == null) { - LOG.warn("Location null for {}", className); - } - - if (!className.isEmpty() && !verifyAction(className, name, location)) { - LOG.error("Unable to verify action [{}] with class [{}], from [{}]", name, className, location); - return; + if (!className.isEmpty()) { + verifyAction(className, name, location); } Map<String, ResultConfig> results; @@ -499,17 +506,18 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid */ @Deprecated protected boolean verifyAction(String className, String name, Location loc) { - return verifyAction(className, loc); + verifyAction(className, loc); + return true; } - protected boolean verifyAction(String className, Location loc) { + protected void verifyAction(String className, Location loc) { if (className.contains("{")) { LOG.debug("Action class [{}] contains a wildcard replacement value, so it can't be verified", className); - return true; + return; } try { if (objectFactory.isNoArgConstructorRequired()) { - Class<?> clazz = loadClass(className); + Class<?> clazz = allowAndLoadClass(className); if (!Modifier.isPublic(clazz.getModifiers())) { throw new ConfigurationException("Action class [" + className + "] is not public", loc); } @@ -530,7 +538,6 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid LOG.debug("Unable to verify action class [{}]", className, ex); throw new ConfigurationException(ex, loc); } - return true; } protected void addResultTypes(PackageConfig.Builder packageContext, Element element) { @@ -572,7 +579,7 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid protected Class<?> verifyResultType(String className, Location loc) { try { - return loadClass(className); + return allowAndLoadClass(className); } catch (ClassNotFoundException | NoClassDefFoundError e) { LOG.warn("Result class [{}] doesn't exist ({}) at {}, ignoring", className, e.getClass().getSimpleName(), loc, e); } @@ -888,7 +895,12 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid NodeList defaultClassRefList = element.getElementsByTagName("default-class-ref"); if (defaultClassRefList.getLength() > 0) { Element defaultClassRefElement = (Element) defaultClassRefList.item(0); - packageContext.defaultClassRef(defaultClassRefElement.getAttribute("class")); + + String className = defaultClassRefElement.getAttribute("class"); + Location location = DomHelper.getLocationObject(defaultClassRefElement); + verifyAction(className, location); + + packageContext.defaultClassRef(className); } } @@ -927,10 +939,25 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid iterateChildrenByTagName( element, "interceptor", - interceptorElement -> context.addInterceptorConfig(buildInterceptorConfig(interceptorElement))); + interceptorElement -> { + String className = interceptorElement.getAttribute("class"); + Location location = DomHelper.getLocationObject(interceptorElement); + + verifyInterceptor(className, location); + + context.addInterceptorConfig(buildInterceptorConfig(interceptorElement)); + }); loadInterceptorStacks(element, context); } + protected void verifyInterceptor(String className, Location loc) { + try { + allowAndLoadClass(className); + } catch (ClassNotFoundException | NoClassDefFoundError e) { + LOG.warn("Interceptor class [{}] doesn't exist at {}, ignoring", className, loc, e); + } + } + protected InterceptorConfig buildInterceptorConfig(Element interceptorElement) { String interceptorName = interceptorElement.getAttribute("name"); String className = interceptorElement.getAttribute("class");