Handle ArrayIndexOutOfBoundsException if we are always out of bounds.

Fixes IDEA-246054 Incorrect condition is always true due to ignored ArrayIndexOutOfBounds catch

GitOrigin-RevId: 4d783f58e587e9cede2e63813583baaec5ece3bd
This commit is contained in:
Tagir Valeev
2020-07-20 08:34:18 +00:00
committed by intellij-monorepo-bot
parent 08546fe04a
commit a4905164a8
5 changed files with 36 additions and 6 deletions
@@ -1235,7 +1235,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
if (toPush == null) {
toPush = myFactory.getObjectType(expression.getType(), Nullability.UNKNOWN);
}
addInstruction(new ArrayAccessInstruction(toPush, expression));
DfaControlTransferValue transfer =
shouldHandleException() ? myFactory.controlTransfer(myExceptionCache.get("java.lang.ArrayIndexOutOfBoundsException"), myTrapStack) : null;
addInstruction(new ArrayAccessInstruction(toPush, expression, transfer));
addNullCheck(expression);
finishElement(expression);
}
@@ -179,6 +179,14 @@ public class StandardInstructionVisitor extends InstructionVisitor {
}
processArrayAccess(arrayExpression, alwaysOutOfBounds);
if (alwaysOutOfBounds) {
DfaControlTransferValue transfer = instruction.getOutOfBoundsExceptionTransfer();
if (transfer != null) {
List<DfaInstructionState> states = transfer.dispatch(memState, runner);
for (DfaInstructionState state : states) {
state.getMemoryState().markEphemeral();
}
return states.toArray(DfaInstructionState.EMPTY_ARRAY);
}
return DfaInstructionState.EMPTY_ARRAY;
}
@@ -15,22 +15,29 @@
*/
package com.intellij.codeInspection.dataFlow.instructions;
import com.intellij.codeInspection.dataFlow.DataFlowRunner;
import com.intellij.codeInspection.dataFlow.DfaInstructionState;
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
import com.intellij.codeInspection.dataFlow.InstructionVisitor;
import com.intellij.codeInspection.dataFlow.*;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.psi.PsiArrayAccessExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class ArrayAccessInstruction extends ExpressionPushingInstruction<PsiArrayAccessExpression> {
private final @NotNull DfaValue myValue;
private final @Nullable DfaControlTransferValue myTransferValue;
public ArrayAccessInstruction(@NotNull DfaValue value, @NotNull PsiArrayAccessExpression expression) {
public ArrayAccessInstruction(@NotNull DfaValue value,
@NotNull PsiArrayAccessExpression expression,
@Nullable DfaControlTransferValue transferValue) {
super(expression);
myValue = value;
myTransferValue = transferValue;
}
@Nullable
public DfaControlTransferValue getOutOfBoundsExceptionTransfer() {
return myTransferValue;
}
@NotNull
@@ -0,0 +1,12 @@
class X {
// IDEA-246054
void test(int[] data) {
for (int i = -1; i < data.length; i++) {
try {
data[i] = 0;
} catch (ArrayIndexOutOfBoundsException ignored) {
}
}
}
}
@@ -675,4 +675,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testDefaultConstructor() { doTest(); }
public void testInstanceOfUnresolved() { doTest(); }
public void testProtobufNotNullGetters() { doTest(); }
public void testAIOOBETransfer() { doTest(); }
}