Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer public methods over made-up ones that happen to exist and be private #661

Open
grishka opened this issue Oct 11, 2023 · 0 comments
Open

Comments

@grishka
Copy link

grishka commented Oct 11, 2023

If a class has a public method something() and a private method hasSomething(), Pebble would first try to call the latter one and that would cause an exception to be thrown if the class is part of JDK. I just ran into this behavior once again. Template:

{{ to.iterator().next() }}

Exception:

java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.ImmutableCollections$Set12$1.hasNext() accessible: module java.base does not "opens java.util" to unnamed module @4e04a765
	at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
	at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:203)
	at java.base/java.lang.reflect.Method.setAccessible(Method.java:197)
	at io.pebbletemplates.pebble.attributes.MemberCacheUtils.reflect(MemberCacheUtils.java:103)
	at io.pebbletemplates.pebble.attributes.MemberCacheUtils.cacheMember(MemberCacheUtils.java:32)
	at io.pebbletemplates.pebble.attributes.DefaultAttributeResolver.resolve(DefaultAttributeResolver.java:64)
	at io.pebbletemplates.pebble.node.expression.GetAttributeExpression.evaluate(GetAttributeExpression.java:83)
	at io.pebbletemplates.pebble.node.expression.FilterExpression.evaluate(FilterExpression.java:66)
	at io.pebbletemplates.pebble.node.PrintNode.render(PrintNode.java:37)
	at io.pebbletemplates.pebble.node.BodyNode.render(BodyNode.java:44)
	at io.pebbletemplates.pebble.node.RootNode.render(RootNode.java:31)
	at io.pebbletemplates.pebble.template.PebbleTemplateImpl.evaluate(PebbleTemplateImpl.java:157)
	at io.pebbletemplates.pebble.template.PebbleTemplateImpl.evaluate(PebbleTemplateImpl.java:105)
	at smithereen.templates.RenderedTemplateResponse.renderToWriter(RenderedTemplateResponse.java:103)
	at smithereen.SmithereenApplication.lambda$main$45(SmithereenApplication.java:614)
...

I never intended to call hasNext(), I wanted to call literally what I wrote but Pebble won't let me.

The problem is here: https://github.com/PebbleTemplates/pebble/blob/master/pebble/src/main/java/io/pebbletemplates/pebble/attributes/MemberCacheUtils.java#L68-L100
It first checks all the made-up methods, and only then, if none of them exist (regardless of the access), looks for the one I intended. That could lead to all kinds of hard-to-debug bugs. IMO "check if attribute is a public method" should come first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant