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 <[email protected]>
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>

Reply via email to