-
Notifications
You must be signed in to change notification settings - Fork 578
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
Ignore checkcast in Java 21 type switch #2813
Merged
Merged
Changes from 5 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
f583c14
Failing test case
robinjhector e688dc9
Merge branch 'master' of https://github.com/spotbugs/spotbugs.git int…
gtoison d0c3f34
fix: applied spotless
gtoison 6b03922
test: issue #2782 reproducer
gtoison 6c80999
fix: look for java 21 type switches and ignore corresponding casts
gtoison 50e9121
test: enable the compilation of java 21 samples
gtoison ced58a5
ci: build on JDK 21 only now that there are Java 21 bug samples
gtoison 3923cbd
doc: added changelog entries
gtoison d34ca83
fix: look for PC-1 (aload_<n>) or PC-2 (aload)
gtoison 6b74fd3
ci: reverted to building on JDK 17 and 21
gtoison 72dafab
test: added some tests checking that we can spot bad casts in a switch
gtoison 300d20e
doc: rephrased jdk requirements
gtoison faa59af
Merge branch 'master' into master
hazendaz File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
spotbugs-tests/src/test/java/edu/umd/cs/findbugs/detect/Issue2782Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package edu.umd.cs.findbugs.detect; | ||
|
||
import edu.umd.cs.findbugs.AbstractIntegrationTest; | ||
import edu.umd.cs.findbugs.BugCollection; | ||
import edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher; | ||
import edu.umd.cs.findbugs.test.matcher.BugInstanceMatcherBuilder; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static edu.umd.cs.findbugs.test.CountMatcher.containsExactly; | ||
import static org.hamcrest.MatcherAssert.*; | ||
|
||
import edu.umd.cs.findbugs.test.SpotBugsRunner; | ||
import edu.umd.cs.findbugs.test.SpotBugsExtension; | ||
|
||
import org.junit.jupiter.api.extension.ExtendWith; | ||
|
||
import java.nio.file.Paths; | ||
|
||
@ExtendWith(SpotBugsExtension.class) | ||
class Issue2782Test extends AbstractIntegrationTest { | ||
|
||
@Test | ||
void testIssue(SpotBugsRunner spotbugs) { | ||
BugCollection bugCollection = spotbugs.performAnalysis( | ||
Paths.get("../spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782.class"), | ||
Paths.get("../spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782$MyInterface.class"), | ||
Paths.get("../spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782$Impl1.class"), | ||
Paths.get("../spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782$Impl2.class")); | ||
|
||
BugInstanceMatcher matcher = new BugInstanceMatcherBuilder() | ||
.bugType("BC_UNCONFIRMED_CAST") | ||
.build(); | ||
|
||
assertThat(bugCollection, containsExactly(0, matcher)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,9 @@ | |
package edu.umd.cs.findbugs; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import javax.annotation.CheckForNull; | ||
|
||
|
@@ -32,9 +34,11 @@ | |
|
||
public class SwitchHandler { | ||
private final List<SwitchDetails> switchOffsetStack; | ||
private final Set<Integer> typeSwitchPcs; | ||
|
||
public SwitchHandler() { | ||
switchOffsetStack = new ArrayList<>(); | ||
typeSwitchPcs = new HashSet<>(); | ||
} | ||
|
||
public int stackSize() { | ||
|
@@ -55,11 +59,13 @@ int numEnumValues(@CheckForNull XClass c) { | |
} | ||
|
||
public void enterSwitch(DismantleBytecode dbc, @CheckForNull XClass enumType) { | ||
|
||
assert dbc.getOpcode() == Const.TABLESWITCH || dbc.getOpcode() == Const.LOOKUPSWITCH; | ||
int[] switchOffsets = dbc.getSwitchOffsets(); | ||
SwitchDetails details = new SwitchDetails(dbc.getPC(), switchOffsets, dbc.getDefaultSwitchOffset(), switchOffsets.length == numEnumValues( | ||
enumType)); | ||
enterSwitch(dbc.getOpcode(), dbc.getPC(), switchOffsets, dbc.getDefaultSwitchOffset(), switchOffsets.length == numEnumValues(enumType)); | ||
} | ||
|
||
public void enterSwitch(int opCode, int pc, int[] switchOffsets, int defaultSwitchOffset, @CheckForNull boolean exhaustive) { | ||
assert opCode == Const.TABLESWITCH || opCode == Const.LOOKUPSWITCH; | ||
SwitchDetails details = new SwitchDetails(pc, switchOffsets, defaultSwitchOffset, exhaustive); | ||
|
||
|
||
int size = switchOffsetStack.size(); | ||
|
@@ -120,6 +126,45 @@ public SourceLineAnnotation getCurrentSwitchStatement(BytecodeScanningDetector d | |
detector.getClassContext(), detector, details.switchPC, details.switchPC + details.maxOffset - 1); | ||
} | ||
|
||
public void sawInvokeDynamic(int pc, String methodName) { | ||
if ("typeSwitch".equals(methodName)) { | ||
typeSwitchPcs.add(pc + 5); | ||
} | ||
} | ||
|
||
/** | ||
* @param opCode The operation code | ||
* @param pc The program counter | ||
* @return <code>true</code>If this instruction is a cast for a type switch | ||
*/ | ||
public boolean isTypeSwitchCaseCheckCast(int opCode, int pc) { | ||
if (opCode != Const.CHECKCAST) { | ||
return false; | ||
} | ||
|
||
// For a type switch each case starts with an aload_2 followed by a checkcast | ||
// Since we're on a checkcast look for a switch with a target on the previous PC | ||
SwitchDetails switchDetails = findSwitchDetailsByPc(pc - 1); | ||
|
||
if (switchDetails != null) { | ||
return typeSwitchPcs.contains(switchDetails.switchPC); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private SwitchDetails findSwitchDetailsByPc(int pc) { | ||
for (SwitchDetails switchDetails : switchOffsetStack) { | ||
for (int i = 0; i < switchDetails.swOffsets.length; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Couldn't this be a second foreach loop? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have made the change |
||
if (pc == switchDetails.swOffsets[i] + switchDetails.switchPC) { | ||
return switchDetails; | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public static class SwitchDetails { | ||
final int switchPC; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+631 Bytes
spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782$Impl1.class
Binary file not shown.
Binary file added
BIN
+633 Bytes
spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782$Impl2.class
Binary file not shown.
Binary file added
BIN
+253 Bytes
spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782$MyInterface.class
Binary file not shown.
Binary file added
BIN
+1.7 KB
spotbugsTestCases/src/classSamples/java21typeSwitchSample/Issue2782.class
Binary file not shown.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 essentially "if not...else" which is a double negative. Perhaps refactor to "if null then return false".
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 have made the change