diff --git a/CHANGELOG.md b/CHANGELOG.md index 5de9e9ea76a..e0e1ab2f96d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Currently the versioning policy of this project follows [Semantic Versioning v2. - Make TypeQualifierResolver recognize org.apache.avro.reflect.Nullable ([#2066](https://github.com/spotbugs/spotbugs/pull/2066)) - New detector `FindArgumentAssertions` detecting bug `ASSERTION_OF_ARGUMENTS` in case of validation of arguments of public functions using assertions (See [MET01-J. Never use assertions to validate method arguments](https://wiki.sei.cmu.edu/confluence/display/java/MET01-J.+Never+use+assertions+to+validate+method+arguments)) - Add new detector `CT_CONSTRUCTOR_THROW` for detecting constructors that throw exceptions. +- New detector `FindIncreasedAccessibilityOfMethods` for new bug type `IAOM_DO_NOT_INCREASE_METHOD_ACCESSIBILITY`. This detector reports a bug if a class increases the accessibility of overridden or hidden methods. (See [SEI CERT rule MET04-J](https://wiki.sei.cmu.edu/confluence/display/java/MET04-J.+Do+not+increase+the+accessibility+of+overridden+or+hidden+methods)) ### Security - Disable access to external entities when processing XML ([#2217](https://github.com/spotbugs/spotbugs/pull/2217)) diff --git a/spotbugs-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java b/spotbugs-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java new file mode 100644 index 00000000000..34cf92ffcc3 --- /dev/null +++ b/spotbugs-tests/src/test/java/edu/umd/cs/findbugs/detect/FindIncreasedAccessibilityOfMethodsTest.java @@ -0,0 +1,97 @@ +package edu.umd.cs.findbugs.detect; + +import edu.umd.cs.findbugs.AbstractIntegrationTest; +import edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher; +import edu.umd.cs.findbugs.test.matcher.BugInstanceMatcherBuilder; +import org.junit.Test; + +import static edu.umd.cs.findbugs.test.CountMatcher.containsExactly; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; + +public class FindIncreasedAccessibilityOfMethodsTest extends AbstractIntegrationTest { + + @Test + public void findIAOMBugInClass_IncreasedAccessibilityOfMethods_SubClassFromSamePackage() { + performAnalysis( + "increasedAccessibilityOfMethods/SuperClassOfSuperClass.class", + "increasedAccessibilityOfMethods/SuperClass.class", + "increasedAccessibilityOfMethods/SubClassFromSamePackage.class"); + + assertNumberOfIAOMBugs(6); + + assertIAOMBug("SubClassFromSamePackage", "protectedMethodToPublic"); + assertIAOMBug("SubClassFromSamePackage", "packagePrivateMethodToPublic"); + assertIAOMBug("SubClassFromSamePackage", "packagePrivateMethodToProtected"); + assertIAOMBug("SubClassFromSamePackage", "superProtectedMethodToPublic"); + assertIAOMBug("SubClassFromSamePackage", "superPackagePrivateMethodToPublic"); + assertIAOMBug("SubClassFromSamePackage", "superPackagePrivateMethodToProtected"); + } + + @Test + public void findIAOMBugInClass_IncreasedAccessibilityOfMethods_SubClassFromAnotherPackage() { + performAnalysis( + "increasedAccessibilityOfMethods/SuperClassOfSuperClass.class", + "increasedAccessibilityOfMethods/SuperClass.class", + "increasedAccessibilityOfMethods/anotherPackage/SubClassFromAnotherPackage.class"); + + assertNumberOfIAOMBugs(1); + + assertIAOMBug("SubClassFromAnotherPackage", "protectedMethodToPublic"); + } + + @Test + public void findNoIAOMBugInClass_IncreasedAccessibilityOfMethods_SubClassFromAnotherPackage() { + performAnalysis( + "increasedAccessibilityOfMethods/SuperClassOfSuperClass.class", + "increasedAccessibilityOfMethods/SuperClass.class", + "increasedAccessibilityOfMethods/anotherPackage/CorrectSubClass.class"); + + assertNumberOfIAOMBugs(0); + } + + @Test + public void findNoIAOMBugInClass_IncreasedAccessibilityOfMethods_CloneableImplementation() { + performAnalysis( + "increasedAccessibilityOfMethods/CloneableImplementation.class"); + + assertNumberOfIAOMBugs(0); + } + + @Test + public void findNoIAOMBugInClass_IncreasedAccessibilityOfMethods_InterfaceImplementation() { + performAnalysis( + "increasedAccessibilityOfMethods/InterfaceImplementation.class"); + + assertNumberOfIAOMBugs(0); + } + + @Test + public void findNoIAOMBugInClass_IncreasedAccessibilityOfMethods_GenericImplementation() { + performAnalysis( + "increasedAccessibilityOfMethods/GenericSuperClass.class", + "increasedAccessibilityOfMethods/GenericSubClass.class"); + + assertNumberOfIAOMBugs(3); + + assertIAOMBug("GenericSubClass", "protectedMethodToPublicWithGenericParameter"); + assertIAOMBug("GenericSubClass", "packagePrivateMethodToPublicWithGenericParameter"); + assertIAOMBug("GenericSubClass", "packagePrivateMethodToProtectedWithGenericParameter"); + } + + private void assertNumberOfIAOMBugs(int numberOfBugs) { + BugInstanceMatcher bugTypeMatcher = new BugInstanceMatcherBuilder() + .bugType("IAOM_DO_NOT_INCREASE_METHOD_ACCESSIBILITY").build(); + assertThat(getBugCollection(), containsExactly(numberOfBugs, bugTypeMatcher)); + } + + private void assertIAOMBug(String className, String methodName) { + BugInstanceMatcher bugInstanceMatcher = new BugInstanceMatcherBuilder() + .bugType("IAOM_DO_NOT_INCREASE_METHOD_ACCESSIBILITY") + .inClass(className) + .inMethod(methodName) + .build(); + assertThat(getBugCollection(), hasItem(bugInstanceMatcher)); + } + +} diff --git a/spotbugs/etc/findbugs.xml b/spotbugs/etc/findbugs.xml index ea5c8ed694a..d3df38e09ea 100644 --- a/spotbugs/etc/findbugs.xml +++ b/spotbugs/etc/findbugs.xml @@ -679,8 +679,11 @@ reports="VSC_VULNERABLE_SECURITY_CHECK_METHODS"/> - -