You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2020/06/15 00:16:11 UTC

[freemarker] 02/03: [FREEMARKER-133] Fixed bug where FreeMarker sometimes tries to expose public methods that are defined or overridden in a non-public class, if the non-public class was then extended by a public class. Calling such method just ends up with IllegalAccessException, but they shouldn't be exposed on the first place, and furthermore can sometimes hide the callable version of the method.

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

ddekany pushed a commit to branch 2.3-gae
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 09f247247faa894cddcfa8b36c1d7149106b73be
Author: ddekany <dd...@apache.org>
AuthorDate: Mon Jun 15 01:38:10 2020 +0200

    [FREEMARKER-133] Fixed bug where FreeMarker sometimes tries to expose public methods that are defined or overridden in a non-public class, if the non-public class was then extended by a public class. Calling such method just ends up with IllegalAccessException, but they shouldn't be exposed on the first place, and furthermore can sometimes hide the callable version of the method.
---
 .../freemarker/ext/beans/ClassIntrospector.java    | 38 ++++++++++++----------
 src/manual/en_US/book.xml                          | 17 ++++++++++
 2 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/src/main/java/freemarker/ext/beans/ClassIntrospector.java b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
index 32053f2..36b2511 100644
--- a/src/main/java/freemarker/ext/beans/ClassIntrospector.java
+++ b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
@@ -775,25 +775,27 @@ class ClassIntrospector {
                 Method[] methods = clazz.getMethods();
                 for (int i = 0; i < methods.length; i++) {
                     Method method = methods[i];
-                    ExecutableMemberSignature sig = new ExecutableMemberSignature(method);
-                    // Contrary to intuition, a class can actually have several
-                    // different methods with same signature *but* different
-                    // return types. These can't be constructed using Java the
-                    // language, as this is illegal on source code level, but
-                    // the compiler can emit synthetic methods as part of
-                    // generic type reification that will have same signature
-                    // yet different return type than an existing explicitly
-                    // declared method. Consider:
-                    // public interface I<T> { T m(); }
-                    // public class C implements I<Integer> { Integer m() { return 42; } }
-                    // C.class will have both "Object m()" and "Integer m()" methods.
-                    List<Method> methodList = accessibles.get(sig);
-                    if (methodList == null) {
-                     // TODO Collection.singletonList is more efficient, though read only.
-                        methodList = new LinkedList<>();
-                        accessibles.put(sig, methodList);
+                    if (Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
+                        ExecutableMemberSignature sig = new ExecutableMemberSignature(method);
+                        // Contrary to intuition, a class can actually have several
+                        // different methods with same signature *but* different
+                        // return types. These can't be constructed using Java the
+                        // language, as this is illegal on source code level, but
+                        // the compiler can emit synthetic methods as part of
+                        // generic type reification that will have same signature
+                        // yet different return type than an existing explicitly
+                        // declared method. Consider:
+                        // public interface I<T> { T m(); }
+                        // public class C implements I<Integer> { Integer m() { return 42; } }
+                        // C.class will have both "Object m()" and "Integer m()" methods.
+                        List<Method> methodList = accessibles.get(sig);
+                        if (methodList == null) {
+                            // TODO Collection.singletonList is more efficient, though read only.
+                            methodList = new LinkedList<>();
+                            accessibles.put(sig, methodList);
+                        }
+                        methodList.add(method);
                     }
-                    methodList.add(method);
                 }
                 return;
             } catch (SecurityException e) {
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index c779e01..29dce43 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -29329,6 +29329,23 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <literal>java.beans.Introspector</literal> behavior has changed
               with Java 9.)</para>
             </listitem>
+
+            <listitem>
+              <para><link
+              xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-133">FREEMARKER-133</link>:
+              Fixed bug where FreeMarker sometimes tries to expose public
+              methods that are defined or overridden in a non-public class, if
+              the non-public class was then extended by a public class.
+              Calling such method just ends up with
+              <literal>IllegalAccessException</literal>, but they shouldn't be
+              exposed on the first place. Furthermore, such a wrong method
+              sometimes replaces the good version of the method, which would
+              be callable. When this glitch happens is somewhat unpredictable,
+              as it also depends on what methods
+              <literal>java.beans.Introspector</literal> exposes (which at
+              very least can depend on the Java version), and in what
+              order.</para>
+            </listitem>
           </itemizedlist>
         </section>
       </section>