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 48208e0c783cf5f96b9887f959d3042b260f3e79
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 2d3d0b96b6..e7f33bb8e3 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 ca15a25055..465e6faaa3 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 089311352d..a07fe17e74 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