This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 321b910465b77fd1916157cb895f452b7597209f Author: opencode <[email protected]> AuthorDate: Wed Oct 14 09:58:38 2026 +0200 Avoid invoking unsupported-type setters with null in IntrospectionUtils In setProperty(), the loop that matches single-argument setters initialised the success flag to true and only cleared it for the supported parameter types (int/Integer/long/Long/boolean/Boolean/ InetAddress) when value conversion or host resolution failed. For a setter whose parameter type was not one of those, the default branch merely logged a trace message, leaving the flag set, so the code invoked the method reflectively with a null argument and returned true. Callers such as SetPropertiesRule, Connector.setAttribute, AbstractEndpoint, WebdavServlet.init and FilterBase therefore skipped their error paths and a misconfiguration went unnoticed, with the targeted property silently set to null. Mark unsupported parameter types as not ok so the setter is not invoked. The property now falls back to the generic setProperty(name, value) handler when the target provides one and invokeSetProperty is true, or the method returns false so the caller can report the failure. As a side benefit, an unsupported overload can no longer shadow a supported overload of the same setter, and digester generated code no longer emits an empty statement for such properties. Adds regression tests covering both the no-fallback and the setProperty-fallback cases. --- .../org/apache/tomcat/util/IntrospectionUtils.java | 5 +++ .../apache/tomcat/util/TestIntrospectionUtils.java | 45 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/java/org/apache/tomcat/util/IntrospectionUtils.java b/java/org/apache/tomcat/util/IntrospectionUtils.java index 78040333a0..0b837c3365 100644 --- a/java/org/apache/tomcat/util/IntrospectionUtils.java +++ b/java/org/apache/tomcat/util/IntrospectionUtils.java @@ -181,6 +181,11 @@ public final class IntrospectionUtils { } // Unknown type } else { + // Unsupported parameter type. Do not invoke the + // method with a null value. Let the caller fall + // back to setProperty(name, value) or handle the + // failure. + ok = false; if (log.isTraceEnabled()) { log.trace("IntrospectionUtils: Unknown type " + paramType.getName()); } diff --git a/test/org/apache/tomcat/util/TestIntrospectionUtils.java b/test/org/apache/tomcat/util/TestIntrospectionUtils.java index 73ea86a80e..e1410f54b0 100644 --- a/test/org/apache/tomcat/util/TestIntrospectionUtils.java +++ b/test/org/apache/tomcat/util/TestIntrospectionUtils.java @@ -16,6 +16,7 @@ */ package org.apache.tomcat.util; +import java.util.Map; import java.util.Properties; import org.junit.Assert; @@ -156,4 +157,48 @@ public class TestIntrospectionUtils { properties.setProperty("replaceMe", "something ${replaceMe}"); IntrospectionUtils.replaceProperties("${replaceMe}", properties, null, null); } + + + // A setter with an unsupported parameter type must not be silently + // invoked with a null value. + + @Test + public void testSetPropertyUnsupportedTypeNoFallback() { + TesterBean bean = new TesterBean(); + Assert.assertFalse(IntrospectionUtils.setProperty(bean, "unsupported", "value", false)); + Assert.assertNull(bean.getUnsupported()); + Assert.assertFalse(bean.isGenericCalled()); + } + + + @Test + public void testSetPropertyUnsupportedTypeWithFallback() { + TesterBean bean = new TesterBean(); + Assert.assertTrue(IntrospectionUtils.setProperty(bean, "unsupported", "value", true)); + Assert.assertNull(bean.getUnsupported()); + Assert.assertTrue(bean.isGenericCalled()); + } + + + public static class TesterBean { + + private Map<Object, Object> unsupported; + private boolean genericCalled; + + public void setUnsupported(Map<Object, Object> unsupported) { + this.unsupported = unsupported; + } + + public Map<Object, Object> getUnsupported() { + return unsupported; + } + + public void setProperty(String name, String value) { + genericCalled = true; + } + + public boolean isGenericCalled() { + return genericCalled; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
