-
Notifications
You must be signed in to change notification settings - Fork 25.7k
Fix method visibility in public-callers-finder #137200
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
Fix method visibility in public-callers-finder #137200
Conversation
… public callers. Relates to ES-13117
Relates to ES-13117
|
Pinging @elastic/es-core-infra (Team:Core/Infra) |
|
|
||
| import static java.util.Collections.emptySet; | ||
|
|
||
| public class AccessibleJdkMethods { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is moved here from JdkApiExtractor to make it accessible as common tool
| return Collections.unmodifiableMap(modulesExports); | ||
| } | ||
|
|
||
| public static Map<String, String> loadClassToModuleMapping() throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved here from JdkApiExtractor
| protected FindUsagesClassVisitor(Set<String> moduleExports, MethodDescriptor methodToFind, CallerConsumer callers) { | ||
| protected FindUsagesClassVisitor( | ||
| MethodDescriptor methodToFind, | ||
| Predicate<MethodDescriptor> isPublicAccessible, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than calculating visibility (and potentially having to follow interfaces / super classes), use a predicate based on a precalculated set of accessible method descriptors leveraging the new AccessibleJdkMethods
ldematte
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
I know this is "just a tool", but give its complexity I do wonder if some parts deserve "unit" tests. I'm thinking in particular at AccessibleJdkMethods and some of the logic in Main, e.g. findTransitiveUsages.
As a follow-up. Wdyt?
| return; | ||
| } | ||
| if (moduleClass.clazz.startsWith("com/sun/") && moduleClass.clazz.contains("/internal/")) { | ||
| // skip com.sun.*.internal classes as they are not part of the supported JDK API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do wonder though: should we instrument those as always denied? If they are publicly accessible?
(surely not part of this PR! But it just occurred to me now)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a tricky one, some of these implement public accessible interfaces. Theoretically, if leaked / returned somewhere we could invoke such code in user land. And obviously, without this filter, these would be reported.
In the end this is purely based on the assumption / hope that no JDK API leaks such instances to keep the set of reported methods more manageable and avoid general noise on internal stuff when diffing between different JDKs.
I do wonder though: should we instrument those as always denied?
But I agree, we probably want to verify that assumption. We could deny any access to such classes from "user code" or at least log warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously this was done at the very end prior to writing the result, see
Lines 112 to 116 in 80d91ce
| if (entry.getKey().clazz.startsWith("com/sun/") && entry.getKey().clazz.contains("/internal/")) { | |
| // skip com.sun.*.internal classes as they are not part of the supported JDK API | |
| // even if methods override some publicly visible API | |
| return false; | |
| } |
In fact, that's the same as not visiting such classes at all.
If you prefer to not filter these I'll remove, certainly not as harmful as the exclusions in #137193.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could deny any access to such classes from "user code" or at least log warnings.
That what I was thinking too.
RE: this PR, I'm fine either way (keeping it as-is or remove the excludes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a follow up task for this
| this.accessibleImplementations = newSortedSet(); | ||
| } | ||
|
|
||
| private ModuleClass getModuleClass(String name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: to make the code more readable, getModuleClassFromName?
| boolean publicMethod, | ||
| boolean protectedMethod | ||
| ) { | ||
| public static EnumSet<ExternalAccess> fromPermissions(boolean publicAccessible, boolean publicMethod, boolean protectedMethod) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do wonder if reducing to ExternalAccess is still a good choice? Or if we should just dump/propagate these 3 booleans to the CSV?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was actually thinking the same, but stopped myself from making yet another change. But I think you're right, I'll have another look to see if this can be done with some decent effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Can definitely be a follow-up though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'll do as a follow up, this will impact a lot of places
ldematte
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Public-callers-finder did not correctly report if methods are externally visible due to the following issues: - checking if interfaces are exported (see findAccessibility) must be done using the exports of the interface’s module, not the exports of the current class - super classes must be treated the same way as interfaces, currently these are ignored - currently all public methods of a (potentially private, non-exported) class implementing a public, exported interface are considered accessible / visible regardless if part of the interface or not This fixes visibility to be consistent with the JdkApiExtractor tool by implementing both using the same common logic in `AccessibleJdkMethods.loadAccessibleMethods`. Note: this currently includes elastic#137193, which will be merged independently. Relates to ES-13117
Public-callers-finder did not correctly report if methods are externally visible due to the following issues: - checking if interfaces are exported (see findAccessibility) must be done using the exports of the interface’s module, not the exports of the current class - super classes must be treated the same way as interfaces, currently these are ignored - currently all public methods of a (potentially private, non-exported) class implementing a public, exported interface are considered accessible / visible regardless if part of the interface or not This fixes visibility to be consistent with the JdkApiExtractor tool by implementing both using the same common logic in `AccessibleJdkMethods.loadAccessibleMethods`. Note: this currently includes elastic#137193, which will be merged independently. Relates to ES-13117
Public-callers-finder did not correctly report if methods are externally visible due to the following issues:
This fixes visibility to be consistent with the JdkApiExtractor tool by implementing both using the same common logic in
AccessibleJdkMethods.loadAccessibleMethods.Note: this currently includes #137193, which will be merged independently.
Relates to ES-13117