Skip to content

Commit 6187386

Browse files
SONARJAVA-6112 S8446 Fix NPE when accessing super with broken semantics (#5496)
Co-authored-by: Tomasz Tylenda <tomasz.tylenda@sonarsource.com>
1 parent 2014da5 commit 6187386

3 files changed

Lines changed: 40 additions & 7 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class MultipleMainInstancesSample {
2+
public class UnknownSuper extends UndefinedParent {
3+
void main() { // Compliant - cannot verify if UndefinedParent has a main method
4+
}
5+
}
6+
7+
// Decoy non-compliant example in the non-compiling test, so we can verifyIssues
8+
public static class NonCompliant {
9+
public static void main(String[] args) { // Noncompliant {{At most one main method should be defined in a class.}}
10+
// ^^^^
11+
System.out.println("Static main detected; shadowing instance main.");
12+
}
13+
14+
void main() {
15+
System.out.println("Unreachable entry point due to static precedence.");
16+
}
17+
}
18+
}

java-checks/src/main/java/org/sonar/java/checks/MultipleMainInstancesCheck.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ private List<MethodTree> findMainMethodsInSuperclasses(ClassTree ct) {
8282
var superClass = ct.superClass();
8383
while (superClass != null) {
8484
var superClassTree = superClass.symbolType().symbol().declaration();
85+
if (superClassTree == null) {
86+
break;
87+
}
8588
findMainMethodsInMembers(superClassTree)
8689
.forEach(mains::add);
8790
superClass = superClassTree.superClass();

java-checks/src/test/java/org/sonar/java/checks/MultipleMainInstancesCheckTest.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,38 @@
1616
*/
1717
package org.sonar.java.checks;
1818

19-
import org.junit.jupiter.api.Test;
19+
import java.util.stream.Stream;
20+
import org.junit.jupiter.params.ParameterizedTest;
21+
import org.junit.jupiter.params.provider.MethodSource;
2022
import org.sonar.java.checks.verifier.CheckVerifier;
2123

2224
import static org.sonar.java.checks.verifier.TestUtils.mainCodeSourcesPath;
25+
import static org.sonar.java.checks.verifier.TestUtils.nonCompilingTestSourcesPath;
2326

2427
class MultipleMainInstancesCheckTest {
2528

26-
@Test
27-
void test() {
29+
static Stream<String> testSamples() {
30+
return Stream.of(
31+
mainCodeSourcesPath("checks/MultipleMainInstancesSample.java"),
32+
nonCompilingTestSourcesPath("checks/MultipleMainInstancesNonCompilingSample.java")
33+
);
34+
}
35+
36+
@ParameterizedTest
37+
@MethodSource("testSamples")
38+
void test(String file) {
2839
CheckVerifier.newVerifier()
29-
.onFile(mainCodeSourcesPath("checks/MultipleMainInstancesSample.java"))
40+
.onFile(file)
3041
.withCheck(new MultipleMainInstancesCheck())
3142
.withJavaVersion(25)
3243
.verifyIssues();
3344
}
3445

35-
@Test
36-
void test_java_24() {
46+
@ParameterizedTest
47+
@MethodSource("testSamples")
48+
void test_java_24(String file) {
3749
CheckVerifier.newVerifier()
38-
.onFile(mainCodeSourcesPath("checks/MultipleMainInstancesSample.java"))
50+
.onFile(file)
3951
.withCheck(new MultipleMainInstancesCheck())
4052
.withJavaVersion(24)
4153
.verifyNoIssues();

0 commit comments

Comments
 (0)