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

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

commit 8910a8038f58acb5f5cd7b746a6d902623f70215
Author: opencode <[email protected]>
AuthorDate: Mon Oct 19 10:17:45 2026 +0200

    Correct the assignability check for Graal bean property writes
    
    GraalBeanELResolver.getWriteMethod() accepted a setter when the
    parameter type was assignable from the value type, which is the
    reverse of what is required to invoke setX(P) with a value of type V,
    namely that P accepts V. As a result, any setter whose parameter type
    was a super-type of the value type, for example a setter taking Object
    or an interface, was rejected. In a GraalVM native image, where this
    resolver stands in for the reflection-configured BeanELResolver, EL
    assignments to such properties were silently dropped and the
    properties were reported as read only.
    
    Flip the check so the write method's parameter type is checked for
    assignability from the value type.
    
    The shipped test encoded the incorrect behaviour by asserting that a
    property with a setBla(Object) setter was read only. That assertion is
    flipped and a regression test is added that verifies a write through a
    super-type setter reaches the bean.
    
    Found by code review.
---
 java/org/apache/jasper/el/JasperELResolver.java     |  2 +-
 test/org/apache/jasper/el/TestJasperELResolver.java | 16 ++++++++++++++--
 webapps/docs/changelog.xml                          |  8 ++++++++
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/java/org/apache/jasper/el/JasperELResolver.java 
b/java/org/apache/jasper/el/JasperELResolver.java
index 0e6368b8fa..6d3fa3e5b9 100644
--- a/java/org/apache/jasper/el/JasperELResolver.java
+++ b/java/org/apache/jasper/el/JasperELResolver.java
@@ -277,7 +277,7 @@ public class JasperELResolver extends CompositeELResolver {
             Method[] methods = beanClass.getMethods();
             for (Method method : methods) {
                 if (method.getParameterCount() == 1 && 
setter.equals(method.getName()) &&
-                        (valueClass == null || 
valueClass.isAssignableFrom(method.getParameterTypes()[0]))) {
+                        (valueClass == null || 
method.getParameterTypes()[0].isAssignableFrom(valueClass))) {
                     return method;
                 }
             }
diff --git a/test/org/apache/jasper/el/TestJasperELResolver.java 
b/test/org/apache/jasper/el/TestJasperELResolver.java
index 3d93d11f55..411a3ebbb8 100644
--- a/test/org/apache/jasper/el/TestJasperELResolver.java
+++ b/test/org/apache/jasper/el/TestJasperELResolver.java
@@ -88,7 +88,14 @@ public class TestJasperELResolver {
         Assert.assertNull(resolver.getValue(context, new TestBean(), 
"foobar"));
         Assert.assertNull(resolver.getValue(context, new TestBean(), "bar"));
         Assert.assertFalse(resolver.isReadOnly(context, new TestBean(), 
"foo"));
-        Assert.assertTrue(resolver.isReadOnly(context, new TestBean(), "bla"));
+        Assert.assertFalse(resolver.isReadOnly(context, new TestBean(), 
"bla"));
+
+        // A setter whose parameter type is a supertype of the value type must
+        // be used. The inverted assignability check in getWriteMethod()
+        // previously rejected such setters, silently dropping the write.
+        TestBean bean = new TestBean();
+        resolver.setValue(context, bean, "bla", "a string value");
+        Assert.assertEquals("a string value", bean.getLastBla());
     }
 
     public static class TestBean {
@@ -108,10 +115,15 @@ public class TestJasperELResolver {
         public String isFoobar() {
             return "foobar";
         }
+        private Object bla;
         public String getBla() {
             return "bla";
         }
-        public void setBla(@SuppressWarnings("unused") Object bla) {
+        public void setBla(Object bla) {
+            this.bla = bla;
+        }
+        public Object getLastBla() {
+            return bla;
         }
     }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index daf328013e..fdd80c265b 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -421,6 +421,14 @@
         text node from being trimmed when <code>trim</code> was
         <code>true</code>. (remm)
       </fix>
+      <fix>
+        Correct the assignability check <code>GraalBeanELResolver</code> uses
+        when selecting a setter for an EL value. The check was inverted, so a
+        setter whose parameter type was a super-type of the value type, for
+        example a setter taking <code>Object</code> or an interface, was
+        rejected and EL writes to such properties could be silently dropped
+        when running in a GraalVM native image. (remm)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="WebSocket">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to