diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayAccessInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayAccessInstruction.java index 6a291711490e..ddedc34bad50 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayAccessInstruction.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayAccessInstruction.java @@ -5,8 +5,8 @@ import com.intellij.codeInspection.dataFlow.TypeConstraint; import com.intellij.codeInspection.dataFlow.interpreter.DataFlowInterpreter; import com.intellij.codeInspection.dataFlow.java.JavaDfaHelpers; import com.intellij.codeInspection.dataFlow.jvm.descriptors.ArrayElementDescriptor; -import com.intellij.codeInspection.dataFlow.lang.DfaAnchor; import com.intellij.codeInspection.dataFlow.jvm.problems.IndexOutOfBoundsProblem; +import com.intellij.codeInspection.dataFlow.lang.DfaAnchor; import com.intellij.codeInspection.dataFlow.lang.ir.DfaInstructionState; import com.intellij.codeInspection.dataFlow.lang.ir.ExpressionPushingInstruction; import com.intellij.codeInspection.dataFlow.lang.ir.Instruction; @@ -19,6 +19,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; public class ArrayAccessInstruction extends ExpressionPushingInstruction { @@ -47,6 +48,10 @@ public class ArrayAccessInstruction extends ExpressionPushingInstruction { public DfaInstructionState[] accept(@NotNull DataFlowInterpreter interpreter, @NotNull DfaMemoryState stateBefore) { DfaValue index = stateBefore.pop(); DfaValue array = stateBefore.pop(); + List finalStates = new ArrayList<>(); + if (myOutOfBoundsTransfer != null) { + finalStates.addAll(IndexOutOfBoundsProblem.dispatchTransfer(interpreter, stateBefore, myOutOfBoundsTransfer)); + } DfaInstructionState[] states = myProblem.processOutOfBounds(interpreter, stateBefore, index, array, myOutOfBoundsTransfer); if (states != null) return states; LongRangeSet rangeSet = DfIntType.extractRange(stateBefore.getDfType(index)); @@ -68,7 +73,8 @@ public class ArrayAccessInstruction extends ExpressionPushingInstruction { } } pushResult(interpreter, stateBefore, result); - return nextStates(interpreter, stateBefore); + finalStates.add(nextState(interpreter, stateBefore)); + return finalStates.toArray(DfaInstructionState.EMPTY_ARRAY); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayStoreInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayStoreInstruction.java index 2efac0aabf77..865beb5cbb3d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayStoreInstruction.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/ArrayStoreInstruction.java @@ -20,6 +20,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -53,6 +54,10 @@ public class ArrayStoreInstruction extends ExpressionPushingInstruction { DfaValue valueToStore = stateBefore.pop(); DfaValue index = stateBefore.pop(); DfaValue array = stateBefore.pop(); + List finalStates = new ArrayList<>(); + if (myOutOfBoundsTransfer != null) { + finalStates.addAll(IndexOutOfBoundsProblem.dispatchTransfer(interpreter, stateBefore, myOutOfBoundsTransfer)); + } DfaInstructionState[] states = myIndexProblem.processOutOfBounds(interpreter, stateBefore, index, array, myOutOfBoundsTransfer); if (states != null) return states; @@ -71,7 +76,8 @@ public class ArrayStoreInstruction extends ExpressionPushingInstruction { stateBefore.flushFieldsQualifiedBy(Set.of(array)); pushResult(interpreter, stateBefore, valueToStore); } - return nextStates(interpreter, stateBefore); + finalStates.add(nextState(interpreter, stateBefore)); + return finalStates.toArray(DfaInstructionState.EMPTY_ARRAY); } protected void checkArrayElementAssignability(@NotNull DataFlowInterpreter interpreter, diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/problems/IndexOutOfBoundsProblem.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/problems/IndexOutOfBoundsProblem.java index 4c3c84dfb3d2..ccbfac838ca2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/problems/IndexOutOfBoundsProblem.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/problems/IndexOutOfBoundsProblem.java @@ -45,14 +45,21 @@ public interface IndexOutOfBoundsProblem extends UnsatisfiedConditionProblem { interpreter.getListener().onCondition(this, index, failed, stateBefore); if (alwaysOutOfBounds) { if (outOfBoundsTransfer != null) { - List states = outOfBoundsTransfer.dispatch(stateBefore, interpreter); - for (DfaInstructionState state : states) { - state.getMemoryState().markEphemeral(); - } + List states = dispatchTransfer(interpreter, stateBefore, outOfBoundsTransfer); return states.toArray(DfaInstructionState.EMPTY_ARRAY); } return DfaInstructionState.EMPTY_ARRAY; } return null; } + + static @NotNull List dispatchTransfer(@NotNull DataFlowInterpreter interpreter, + @NotNull DfaMemoryState stateBefore, + @NotNull DfaControlTransferValue outOfBoundsTransfer) { + List states = outOfBoundsTransfer.dispatch(stateBefore, interpreter); + for (DfaInstructionState state : states) { + state.getMemoryState().markEphemeral(); + } + return states; + } } diff --git a/java/java-tests/testData/inspection/dataFlow/unreachableCode/ArrayIndexOutOfBounds.java b/java/java-tests/testData/inspection/dataFlow/unreachableCode/ArrayIndexOutOfBounds.java new file mode 100644 index 000000000000..0debcd619f9c --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/unreachableCode/ArrayIndexOutOfBounds.java @@ -0,0 +1,22 @@ + +class Test { + static final int[] DATA = {1, 2, 3}; + + int test(int value) { + try { + return DATA[value]; + } + catch (ArrayIndexOutOfBoundsException e) { + return -1; + } + } + + void test2(int value) { + try { + DATA[value] = -1; + } + catch (ArrayIndexOutOfBoundsException e) { + System.out.println(e); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/UnreachableCodeInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/UnreachableCodeInspectionTest.java index 1a2d67e96b78..52b4a3d1eaa9 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/UnreachableCodeInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/UnreachableCodeInspectionTest.java @@ -45,6 +45,8 @@ public class UnreachableCodeInspectionTest extends LightJavaCodeInsightFixtureTe public void testUnresolvedCast() { doTest(); } public void testUnresolvedCall() { doTest(); } + + public void testArrayIndexOutOfBounds() { doTest(); } private void doTest() { myFixture.configureByFile(getTestName(false) + ".java");