This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit dddb947371063e33c139bf589e3dd1e4b419cfe5
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 fc97f8d25b..48092835d2 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 ed9fe394b4..a6b32459ae 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;
@@ -144,4 +145,48 @@ public class TestIntrospectionUtils {
         Assert.assertEquals("abc${normal}xyz", 
IntrospectionUtils.replaceProperties(
                 "abc${normal}xyz", 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]

Reply via email to