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>
