From 3ca2ad32e0422d2a1b216cf9e1f44b6085885e2f Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 25 Jun 2021 14:05:05 +0700 Subject: [PATCH] [java-dfa] DfaBinOpValue: math during backpropagation should be done within the required type Otherwise, we can get the wrong number due to non-processed overflow when negating (for x-Integer.MIN_VALUE) or when collapsing two bin-ops into one Fixes EA-290247 - IAE: DfaBinOpValue. GitOrigin-RevId: 2390830de3b91fb0f6390b75558e565e4fc73a45 --- .../dataFlow/fixture/BackPropagation.java | 5 +++++ .../dataFlow/value/DfaBinOpValue.java | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/BackPropagation.java b/java/java-tests/testData/inspection/dataFlow/fixture/BackPropagation.java index 79b925092013..b58b9c6c6a90 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/BackPropagation.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/BackPropagation.java @@ -135,4 +135,9 @@ public class BackPropagation { } return x * 2; } + + public void backPropagationMinValue(int x) { + if (x - Integer.MIN_VALUE == x + Integer.MIN_VALUE) {} + if (x - 2_000_000_000 - 2_000_000_000 == x + 294967296) {} + } } diff --git a/platform/analysis-api/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java b/platform/analysis-api/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java index 9a590e1d2c0a..ffd2b25aa3c2 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/dataFlow/value/DfaBinOpValue.java @@ -186,7 +186,7 @@ public final class DfaBinOpValue extends DfaValue { long value = rightConst.longValue(); if (value == 0) return left; if (op == LongRangeBinOp.MINUS) { - right = myFactory.fromDfType(resultType.meetRange(LongRangeSet.point(-value))); + right = myFactory.fromDfType(resultType.meetRange(LongRangeSet.point(value).negate(resultType.getLongRangeType()))); } return doCreate((DfaVariableValue)left, right, resultType, LongRangeBinOp.PLUS); } @@ -196,13 +196,14 @@ public final class DfaBinOpValue extends DfaValue { if (sumValue.getOperation() != LongRangeBinOp.PLUS && sumValue.getOperation() != LongRangeBinOp.MINUS) return null; if (rightConst != null) { if (sumValue.getRight() instanceof DfaTypeValue) { - long value1 = extractLong((DfaTypeValue)sumValue.getRight()); - long value2 = rightConst.longValue(); + DfType rightType = sumValue.getRight().getDfType(); + LongRangeSet value1 = ((DfIntegralType)rightType).getRange(); + LongRangeSet value2 = LongRangeSet.point(rightConst.longValue()); if (op == LongRangeBinOp.MINUS) { - value2 = -value2; + value2 = value2.negate(resultType.getLongRangeType()); } - long res = value1 + value2; - right = myFactory.fromDfType(resultType.meetRange(LongRangeSet.point(res))); + LongRangeSet res = value1.plus(value2, resultType.getLongRangeType()); + right = myFactory.fromDfType(resultType.meetRange(res)); return create(sumValue.getLeft(), right, state, resultType, LongRangeBinOp.PLUS); } }