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
Created a new detector for rule MET04-J #1994
base: master
Are you sure you want to change the base?
Conversation
Thanks for the review @ThrawnCA ! Could you please give me a workflow approval as well? 🙏 |
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.
Added several comments, please check them.
Also, could you consider adding one more test, to verify that we can detect cases that publish methods provided not by direct superclass but by other ancestors, such as a parent of the superclass, or the default method defined in an interface?
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Show resolved
Hide resolved
Hey @KengoTODA ! Thanks for you review, I've made the requested changes and also added some test cases (I've made small adjustments on the detector as well). |
Are malicious subclasses really a serious concern? There are reasons that the Security Manager is going away... |
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, thanks for your contribution!
I had to resolve conflicts to be able to merge. Please re-approve my PR and the workflow, thanks! |
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
@ThrawnCA @KengoTODA Please check and approve my PR and workflow once again (and hopefully for the last time 😄). Thank you in advance! |
@ThrawnCA @KengoTODA Hi! I don't want to urge you, I'm just interested - is there any chance that my PR will be included in a future release? |
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 seems to be reverting a bunch of typo fixes.
@ThrawnCA |
@KengoTODA @ThrawnCA I've rebased to the latest master, squashed my previous commits into one, amended my commit message to one which follows the conventional commit rules. Please check this PR one last time, give me a workflow approval and merge if you think that my changes are right too. Thanks in advance and thank you for your work! |
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
7337de4
to
c9827e5
Compare
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
...s/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsCheckTest.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
...s/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsCheckTest.java
Outdated
Show resolved
Hide resolved
841b50e
to
109f07b
Compare
Good point, thanks for trying it! As the SEI CERT rule definition doesn't mention anything specific about constructors, I think you are right, I removed constructors from the analysis - also added some tests to validate if there are no false positive cases of them. If it is okay now, could you please give me a workflow approval? |
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.
Rerun the detector on bigger projects, the links are the same as before, overwrote the earlier results.
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
@Override | ||
public void visitClassContext(ClassContext classContext) { |
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.
In the current implementation there is a hit type, which may cause problems for the users, so we may need filter it out: we have three classes: SuperClass, Class, and SubClass, SuperClass is parent of Class, which is parent of SubClass. We have a method, which is declared in SuperClass as protected, overriden in both Class and SubClass as public. There will be a hit in Class, which is great, but there will be also a hit in SubClass, about which I'm not so sure. If the user have no write access to SuperClass and Class, then can't really do anything about the problem.
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'm not sure, if this can occur in real life. Do SpotBugs analyze classes to which the user has no write access? For example in dependencies? I see your point, can you maybe show me an example of it where I can reproduce the hit?
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.
If the user provided the necessary compiled files for the analysis, even if doesn't have write access to them, cause e.g. they are inside a jar file. Checked every hit of the tests on the bigger projects, but didn't find any test like the one, I mentioned. (Otherwise I would have referred it.) You can create a test by simply creating a class, which descends from one of the hits and overrides the appropriate function, or reusing your already existing test classes, using SuperClassOfSuperClass
as SuperClass in my example, SuperClass
as Class, and SubClassFromSamePackage
as SubClass. If you simply add an override of superPackagePrivateMethodToPublic()
to SuperClass
, then you have the test:
@Override
public String superPackagePrivateMethodToPublic() {
return "SuperClass.superPackagePrivateMethodToPublic";
}
IMO in this case, the error should be only reported in SuperClass
, and not in SubClassFromSamePackage
.
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.
@sajtizsolt Can you please create a testcase like this and modify the code to not to bury our users in hits they can't do anything about?
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 will, I'm just a littly busy nowadays. I will tag you if it happens!
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.
@JuditKnoll Now I thought about this problem again. To achieve the desired behaviour, we should be able to filter out potential bugs based on the bugs already found while we analyzed the super classes of the current class. I don't know, if there is some logic implemented in SpotBugs which enables us to query this list of bugs based on a class, but if there is not, then we should analyze every single super class again. I don't know, I feel that this would increase the complexity of the detector by a huge scale. Do you feel, that the added value of this solution complies with the amount of extra computational demand of it?
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.
Anyway, I've added the requested changes in another commit - take a look at them. Not terribly slow if there are few super classes.
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.
Yes, I think having a more precise detector is worth the increased complexity. Usually there is less than 10 super classes, so it's not as much of an overhead.
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.
However, IMO there is a solution which only needs to check every super class only once, if we take advantage of the order of visiting, and maintain a collection of the correct methods of the examined class. If we phrase the problem like this, that may help: an IAOM bug should be reported, when there is an increase of accessibility of a method from the closest parent declaring/overriding the given method.
When the bug is reported, there is an accessibility increase, then we can remove the current buggy method from the methods of the examined class (subClass
) collection. This way, we don't need to check at every parent whether the same bug got reported or not, also, the number of methods to check against decreases.
Removing a method won't cause a problem, since a method can only have one IAOM bug in one class, and the closer parent will be visited first, since JavaClass.getSuperClasses()
contains the list of super classes in ascending order.
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.
Answering your question about filtering out bugs based on other bugs, there is a solution using BugAccumulator
, but it's a bit different to what you need. As far as I know, that one only works inside one class, not across classes.
f7e75ce
to
b50003f
Compare
@JuditKnoll Can I run CodeChecker with the demo account? I really can't find any way to do it. |
The demo account doesn't have rights to store the results. If you would like to run it yourself, you need to set up a separate codechecker server and configure the runs, which is not so straightforward. |
Thank you! I examined the results and they seem to be valid positive cases to me. What do you think? Can this detector be considered as complete or are there any more edge cases which comes into mind? |
Only the one I mentioned at the detector's visitClassContext() function. |
726ddee
to
c50b170
Compare
} | ||
|
||
@Override | ||
public void visitClassContext(ClassContext classContext) { |
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.
Yes, I think having a more precise detector is worth the increased complexity. Usually there is less than 10 super classes, so it's not as much of an overhead.
} | ||
|
||
@Override | ||
public void visitClassContext(ClassContext classContext) { |
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.
However, IMO there is a solution which only needs to check every super class only once, if we take advantage of the order of visiting, and maintain a collection of the correct methods of the examined class. If we phrase the problem like this, that may help: an IAOM bug should be reported, when there is an increase of accessibility of a method from the closest parent declaring/overriding the given method.
When the bug is reported, there is an accessibility increase, then we can remove the current buggy method from the methods of the examined class (subClass
) collection. This way, we don't need to check at every parent whether the same bug got reported or not, also, the number of methods to check against decreases.
Removing a method won't cause a problem, since a method can only have one IAOM bug in one class, and the closer parent will be visited first, since JavaClass.getSuperClasses()
contains the list of super classes in ascending order.
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
boolean isSameMethodAndAccessibility(IAOMBug other) { | ||
return Objects.equals(method.getSignature(), other.method.getSignature()) |
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.
Are you sure, that checking the signatures is enough to check two methods are the same?
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.
The Method
class itself has an equals, which checks both the name of the method and the signature. Is there any reason, why you don't use that equals?
...-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java
Show resolved
Hide resolved
...-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java
Show resolved
Hide resolved
|
||
List<IAOMBug> superClassBugs = new ArrayList<>(); | ||
for (JavaClass superClass : superClasses) { | ||
superClassBugs.addAll(findIAOMBugs(superClass)); |
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.
It does work, but it could be a bit more efficient, see my comment at the visitClassContext()
method.
} | ||
|
||
@Override | ||
public void visitClassContext(ClassContext classContext) { |
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.
Answering your question about filtering out bugs based on other bugs, there is a solution using BugAccumulator
, but it's a bit different to what you need. As far as I know, that one only works inside one class, not across classes.
Seems like the build is failing, can you please run |
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 you please rebase to the current master and resolve the merge conflicts?
Since your last rebase the project got migrated from Junit to Junit Jupiter (see #2605), which will cause build fail after the rebase, but I commented at the relevant lines, which needs to be modified to work properly.
...-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java
Outdated
Show resolved
Hide resolved
...-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java
Outdated
Show resolved
Hide resolved
...-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java
Outdated
Show resolved
Hide resolved
spotbugs/src/main/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethods.java
Outdated
Show resolved
Hide resolved
7b506b7
to
eacaa5c
Compare
private List<Method> getMethodsExceptConstructors(JavaClass javaClass) { | ||
ArrayList<Method> methods = new ArrayList<>(); | ||
for (Method method : javaClass.getMethods()) { | ||
if (!Const.CONSTRUCTOR_NAME.equals(method.getName())) { |
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 think you can also filter out the static initializer.
} | ||
|
||
boolean isSameMethodAndAccessibility(IAOMBug other) { | ||
return Objects.equals(method.getSignature(), other.method.getSignature()) |
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.
The Method
class itself has an equals, which checks both the name of the method and the signature. Is there any reason, why you don't use that equals?
I've created a new detector for SEI CERT rule MET04-J.
This detector should prevent the happening of increasing accessibility of methods from the super class. This can occur in three ways:
package private
method toprotected
package private
method topublic
protected
method topublic
A noteable exception is the
Cloneable
interface: when a class implements theclone
method, it should increase it's accessiblity fromprotected
topublic
.My changes:
CHANGELOG.md
FindIncreasedAccessibilityOfMethods
inspotbugs
moduleFindIncreasedAccessibilityOfMethodsCheckTest
inspotbugs-tests
modulespotbugs/spotbugsTestCases/src/java/increasedAccessibilityOfMethods
findbugs.xml
andmessages.xml
My tests:
Jenkins
to make sure it works properly../gradlew spotlessApply build smoketest
command locally