Skip to content

Commit 3873563

Browse files
marc-jasper-sonarsourcesonartech
authored andcommitted
SONARPY-4028 Fix valueAsLong() in NumericLiteralImpl to work for floating point values such as 0.0 (#1056)
GitOrigin-RevId: 715a6f8d99450bb09dedf604154c7090107998e1
1 parent 84cfd40 commit 3873563

21 files changed

+113
-29
lines changed

python-checks/src/main/java/org/sonar/python/checks/FastAPIHTTPExceptionDocumentedCheck.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,11 @@ private static Optional<Integer> extractStatusCode(Expression statusCodeExpr) {
261261
return extractStatusCode(singleAssignedValue);
262262
}
263263
} else if (statusCodeExpr instanceof NumericLiteral numericLiteral) {
264-
return Optional.of((int) numericLiteral.valueAsLong());
264+
try {
265+
return Optional.of((int) numericLiteral.valueAsLong());
266+
} catch (NumberFormatException e) {
267+
return Optional.empty();
268+
}
265269
} else if (statusCodeExpr instanceof StringLiteral stringLiteral) {
266270
try {
267271
return Optional.of(Integer.parseInt(stringLiteral.trimmedQuotesValue()));

python-checks/src/main/java/org/sonar/python/checks/FilePermissionsCheck.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ private static boolean isUnsafeExpression(Expression expression, int safeModulo,
9999
}
100100
if (expression.is(Tree.Kind.NUMERIC_LITERAL)) {
101101
NumericLiteral numericLiteral = (NumericLiteral) expression;
102-
return numericLiteral.valueAsLong() % 8 != safeModulo;
102+
try {
103+
return numericLiteral.valueAsLong() % 8 != safeModulo;
104+
} catch (NumberFormatException nfe) {
105+
return false;
106+
}
103107
}
104108
if (expression.is(Tree.Kind.NAME)) {
105109
Expression singleAssignedValue = Expressions.singleAssignedValue(((Name) expression));

python-checks/src/main/java/org/sonar/python/checks/IncorrectParameterDatetimeConstructorsCheck.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,20 @@ public Tree expression() {
102102
}
103103

104104
private static ValueWithExpression getValue(Expression expression) {
105-
if (expression.is(Tree.Kind.NUMERIC_LITERAL)) {
106-
return new ValueWithExpression(((NumericLiteral) expression).valueAsLong(), expression);
107-
} else if (expression.is(Tree.Kind.UNARY_MINUS)) {
108-
UnaryExpression unaryExpression = (UnaryExpression) expression;
109-
if (!unaryExpression.expression().is(Tree.Kind.NUMERIC_LITERAL)) {
110-
return null;
105+
try {
106+
if (expression.is(Tree.Kind.NUMERIC_LITERAL)) {
107+
return new ValueWithExpression(((NumericLiteral) expression).valueAsLong(), expression);
108+
} else if (expression.is(Tree.Kind.UNARY_MINUS)) {
109+
UnaryExpression unaryExpression = (UnaryExpression) expression;
110+
if (!unaryExpression.expression().is(Tree.Kind.NUMERIC_LITERAL)) {
111+
return null;
112+
}
113+
return new ValueWithExpression(-((NumericLiteral) unaryExpression.expression()).valueAsLong(), unaryExpression);
114+
} else if (expression.is(Tree.Kind.NAME)) {
115+
return Expressions.singleAssignedNonNameValue((Name) expression).map(IncorrectParameterDatetimeConstructorsCheck::getValue).orElse(null);
111116
}
112-
return new ValueWithExpression(-((NumericLiteral) unaryExpression.expression()).valueAsLong(), unaryExpression);
113-
} else if (expression.is(Tree.Kind.NAME)) {
114-
return Expressions.singleAssignedNonNameValue((Name) expression).map(IncorrectParameterDatetimeConstructorsCheck::getValue).orElse(null);
117+
} catch (NumberFormatException nfe) {
118+
return null;
115119
}
116120
return null;
117121
}

python-checks/src/main/java/org/sonar/python/checks/UnnecessarySubscriptReversalCheck.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,19 @@ private boolean isSensitiveCall(CallExpression callExpression) {
8888
}
8989

9090
private static boolean isSubscriptReversal(@Nullable Tree expression) {
91-
return expression instanceof SliceExpression sliceExpression
92-
&& sliceExpression.sliceList().slices().size() == 1
93-
&& sliceExpression.sliceList().slices().get(0) instanceof SliceItem sliceItem
94-
&& sliceItem.lowerBound() == null
95-
&& sliceItem.upperBound() == null
96-
&& sliceItem.stride() instanceof UnaryExpression unaryExpression
97-
&& unaryExpression.is(Tree.Kind.UNARY_MINUS)
98-
&& unaryExpression.expression() instanceof NumericLiteral numericLiteral
99-
&& numericLiteral.valueAsLong() == 1;
91+
try {
92+
return expression instanceof SliceExpression sliceExpression
93+
&& sliceExpression.sliceList().slices().size() == 1
94+
&& sliceExpression.sliceList().slices().get(0) instanceof SliceItem sliceItem
95+
&& sliceItem.lowerBound() == null
96+
&& sliceItem.upperBound() == null
97+
&& sliceItem.stride() instanceof UnaryExpression unaryExpression
98+
&& unaryExpression.is(Tree.Kind.UNARY_MINUS)
99+
&& unaryExpression.expression() instanceof NumericLiteral numericLiteral
100+
&& numericLiteral.valueAsLong() == 1;
101+
} catch (NumberFormatException nfe) {
102+
return false;
103+
}
100104
}
101105

102106
private static int getUsageCount(Name name) {

python-checks/src/main/java/org/sonar/python/checks/UseStartsWithEndsWithCheck.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,7 @@ private static SliceType fromSliceItem(SliceItem sliceItem) {
123123
// then we don't check the rule.
124124
if (stride != null &&
125125
!stride.type().mustBeOrExtend(BuiltinTypes.NONE_TYPE) &&
126-
!(stride.is(Tree.Kind.NUMERIC_LITERAL) &&
127-
stride.type().mustBeOrExtend(BuiltinTypes.INT) &&
128-
((NumericLiteral) stride).valueAsLong() == 1)) {
126+
!isIntLiteralEqualTo(stride, 1)) {
129127
return SliceType.COMPLEX;
130128
}
131129

@@ -153,6 +151,16 @@ private static boolean isEmptyBound(@CheckForNull Expression bound) {
153151
}
154152
}
155153

154+
private static boolean isIntLiteralEqualTo(Expression expression, long expected) {
155+
try {
156+
return expression.is(Tree.Kind.NUMERIC_LITERAL)
157+
&& expression.type().mustBeOrExtend(BuiltinTypes.INT)
158+
&& ((NumericLiteral) expression).valueAsLong() == expected;
159+
} catch (NumberFormatException nfe) {
160+
return false;
161+
}
162+
}
163+
156164
private enum OperatorType {
157165
EQUALS,
158166
NOT_EQUALS,

python-checks/src/main/java/org/sonar/python/checks/VerifiedSslTlsCertificateCheck.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,11 @@ private static boolean isFalsyRange(CallExpression callExpr, String fqn) {
433433
Expression firstArgExpr = regArg.expression();
434434
if (firstArgExpr.is(Tree.Kind.NUMERIC_LITERAL)) {
435435
NumericLiteral num = (NumericLiteral) firstArgExpr;
436-
return num.valueAsLong() == 0L;
436+
try {
437+
return num.valueAsLong() == 0L;
438+
} catch (NumberFormatException nfe) {
439+
return false;
440+
}
437441
}
438442
}
439443
}

python-checks/src/main/java/org/sonar/python/checks/cdk/CdkPredicate.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,16 @@ private static boolean anyValueInInterval(Collection<Long> values, long min, lon
194194
}
195195

196196
public static Predicate<Expression> isNumeric(Set<Long> vals) {
197-
return expression -> expression.is(Tree.Kind.NUMERIC_LITERAL) && vals.contains(((NumericLiteral) expression).valueAsLong());
197+
return expression -> {
198+
if (!expression.is(Tree.Kind.NUMERIC_LITERAL)) {
199+
return false;
200+
}
201+
try {
202+
return vals.contains(((NumericLiteral) expression).valueAsLong());
203+
} catch (NumberFormatException nfe) {
204+
return false;
205+
}
206+
};
198207
}
199208

200209
}

python-checks/src/main/java/org/sonar/python/checks/cdk/CdkUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private CdkUtils() {
5555
public static Optional<Integer> getInt(Expression expression) {
5656
try {
5757
return Optional.of((int)((NumericLiteral) expression).valueAsLong());
58-
} catch (ClassCastException e) {
58+
} catch (ClassCastException | NumberFormatException e) {
5959
return Optional.empty();
6060
}
6161
}

python-checks/src/main/java/org/sonar/python/checks/hotspots/CommonValidationUtils.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,12 @@ public static boolean isMoreThan(Expression expression, int number) {
6161
static boolean isLessThanExponent(Expression expression, int exponent) {
6262
if (expression.is(Tree.Kind.SHIFT_EXPR)) {
6363
var shiftExpression = (BinaryExpression) expression;
64-
return shiftExpression.leftOperand().is(Tree.Kind.NUMERIC_LITERAL) && (((NumericLiteral) shiftExpression.leftOperand()).valueAsLong() == 1)
65-
&& isLessThan(shiftExpression.rightOperand(), exponent);
64+
try {
65+
return shiftExpression.leftOperand().is(Tree.Kind.NUMERIC_LITERAL) && (((NumericLiteral) shiftExpression.leftOperand()).valueAsLong() == 1)
66+
&& isLessThan(shiftExpression.rightOperand(), exponent);
67+
} catch (NumberFormatException nfe) {
68+
return false;
69+
}
6670
}
6771
if (expression.is(Tree.Kind.NAME)) {
6872
return Expressions.singleAssignedNonNameValue(((Name) expression))

python-checks/src/main/java/org/sonar/python/checks/tests/UnconditionalAssertionCheck.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,11 @@ private static boolean isFalseOrZeroLiteral(Expression expression) {
103103
return "False".equals(((Name) expression).name());
104104
}
105105
if (expression.is(NUMERIC_LITERAL)) {
106-
return ((NumericLiteral) expression).valueAsLong() == 0;
106+
try {
107+
return ((NumericLiteral) expression).valueAsLong() == 0;
108+
} catch (NumberFormatException nfe) {
109+
return false;
110+
}
107111
}
108112
return false;
109113
}

0 commit comments

Comments
 (0)