C#: Remove redundant ConstantComparison.ql query.

This commit is contained in:
Anders Schack-Mulligen
2026-03-30 11:44:02 +02:00
parent 056be6d504
commit 2a54dce5cb
14 changed files with 54 additions and 145 deletions

View File

@@ -65,7 +65,6 @@ ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql
ql/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql
ql/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql
ql/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql
ql/csharp/ql/src/Likely Bugs/ConstantComparison.ql
ql/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql
ql/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql
ql/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql

View File

@@ -38,7 +38,6 @@ ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql
ql/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql
ql/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql
ql/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql
ql/csharp/ql/src/Likely Bugs/ConstantComparison.ql
ql/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql
ql/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql
ql/csharp/ql/src/Likely Bugs/EqualsArray.ql

View File

@@ -69,7 +69,6 @@ ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql
ql/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql
ql/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql
ql/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql
ql/csharp/ql/src/Likely Bugs/ConstantComparison.ql
ql/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql
ql/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql
ql/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql

View File

@@ -4,19 +4,6 @@ import csharp
private import semmle.code.csharp.commons.ComparisonTest
private import semmle.code.csharp.commons.StructuralComparison as StructuralComparison
pragma[noinline]
private predicate isConstantCondition0(ControlFlow::Node cfn, boolean b) {
exists(cfn.getASuccessorByType(any(ControlFlow::BooleanSuccessor t | t.getValue() = b))) and
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
}
/**
* Holds if `e` is a condition that always evaluates to Boolean value `b`.
*/
predicate isConstantCondition(Expr e, boolean b) {
forex(ControlFlow::Node cfn | cfn = e.getAControlFlowNode() | isConstantCondition0(cfn, b))
}
/**
* Holds if comparison operation `co` is constant with the Boolean value `b`.
* For example, the comparison `x > x` is constantly `false` in

View File

@@ -47,7 +47,6 @@ where
not comparesIdenticalValuesNan(ct, _) and msg = "Comparison of identical values."
) and
not isMutatingOperation(ct.getAnArgument().getAChild*()) and
not isConstantCondition(e, _) and // Avoid overlap with cs/constant-condition
not isConstantComparison(e, _) and // Avoid overlap with cs/constant-comparison
not isConstantComparison(e, _) and // Avoid overlap with cs/constant-condition
not isExprInAssertion(e)
select ct, msg

View File

@@ -1,2 +0,0 @@
for (uint order = numberOfOrders; order >= 0; order--)
ProcessOrder(order);

View File

@@ -1,46 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Comparisons which always yield the same result are unnecessary and may indicate a bug in the
logic. This can happen when the data type of one of the operands has a limited range of values.
For example unsigned integers are always greater than or equal to zero, and <code>byte</code>
values are always less than 256.
</p>
<p>The following expressions always have the same result:</p>
<ul>
<li><code>Unsigned &lt; 0</code> is always false,</li>
<li><code>0 &gt; Unsigned</code> is always false,</li>
<li><code>0 &le; Unsigned</code> is always true,</li>
<li><code>Unsigned &ge; 0</code> is always true,</li>
<li><code>Unsigned == -1</code> is always false,</li>
<li><code>Byte &lt; 512</code> is always true.</li>
</ul>
</overview>
<recommendation>
<p>
Examine the logic of the program to determine whether the comparison is necessary.
Either change the data types, or remove the unnecessary code.
</p>
</recommendation>
<example>
<p>The following example attempts to count down from <code>numberOfOrders</code> to <code>0</code>,
however the loop never terminates because <code>order</code> is an unsigned integer and so the
condition <code>order >= 0</code> is always true.</p>
<sample src="ConstantComparison.cs"/>
<p>The solution is to change the type of the variable <code>order</code>.</p>
</example>
<references>
<li>
MSDN Library: <a href="https://msdn.microsoft.com/en-us/library/6a71f45d.aspx">C# Operators</a>.
</li>
</references>
</qhelp>

View File

@@ -1,22 +0,0 @@
/**
* @name Comparison is constant
* @description The result of the comparison is always the same.
* @kind problem
* @problem.severity warning
* @precision high
* @id cs/constant-comparison
* @tags quality
* reliability
* correctness
*/
import csharp
import semmle.code.csharp.commons.Assertions
import semmle.code.csharp.commons.Constants
from ComparisonOperation cmp, boolean value
where
isConstantComparison(cmp, value) and
not isConstantCondition(cmp, _) and // Avoid overlap with cs/constant-condition
not isExprInAssertion(cmp)
select cmp, "This comparison is always " + value + "."

View File

@@ -22,7 +22,6 @@
- cs/comparison-of-identical-expressions
- cs/complex-block
- cs/complex-condition
- cs/constant-comparison
- cs/constant-condition
- cs/coupled-types
- cs/dereferenced-value-is-always-null

View File

@@ -16,16 +16,16 @@ class Test
{
bool good, bad;
bad = uintValue < 0;
bad = 0 > uintValue;
bad = 0 <= uintValue;
bad = uintValue >= 0;
bad = uintValue < 0; // $ Alert
bad = 0 > uintValue; // $ Alert
bad = 0 <= uintValue; // $ Alert
bad = uintValue >= 0; // $ Alert
bad = uintValue == -1;
bad = uintValue != -1;
bad = 256 == byteValue;
bad = 256 != byteValue;
bad = 1 != 0;
bad = uintValue == -1; // $ Alert
bad = uintValue != -1; // $ Alert
bad = 256 == byteValue; // $ Alert
bad = 256 != byteValue; // $ Alert
bad = 1 != 0; // $ Alert
good = byteValue == 50;
good = 50 != byteValue;
@@ -35,61 +35,61 @@ class Test
good = intValue <= 1u;
good = 1u >= intValue;
good = charValue >= '0'; // Regression
good = charValue >= '0';
good = charValue < '0';
// Test ranges
bad = charValue <= 65535;
bad = charValue >= 0;
bad = charValue <= 65535; // $ Alert
bad = charValue >= 0; // $ Alert
good = charValue < 255;
good = charValue > 0;
bad = byteValue >= byte.MinValue;
bad = byteValue <= byte.MaxValue;
bad = byteValue >= byte.MinValue; // $ Alert
bad = byteValue <= byte.MaxValue; // $ Alert
good = byteValue > byte.MinValue;
good = byteValue < byte.MaxValue;
bad = sbyteValue >= sbyte.MinValue;
bad = sbyteValue <= sbyte.MaxValue;
bad = sbyteValue >= sbyte.MinValue; // $ Alert
bad = sbyteValue <= sbyte.MaxValue; // $ Alert
good = sbyteValue < sbyte.MaxValue;
good = sbyteValue > sbyte.MinValue;
bad = shortValue >= short.MinValue;
bad = shortValue <= short.MaxValue;
bad = shortValue >= short.MinValue; // $ Alert
bad = shortValue <= short.MaxValue; // $ Alert
good = shortValue > short.MinValue;
good = shortValue < short.MaxValue;
bad = ushortValue >= ushort.MinValue;
bad = ushortValue <= ushort.MaxValue;
bad = ushortValue >= ushort.MinValue; // $ Alert
bad = ushortValue <= ushort.MaxValue; // $ Alert
good = ushortValue > ushort.MinValue;
good = ushortValue < ushort.MaxValue;
bad = intValue >= int.MinValue;
bad = intValue <= int.MaxValue;
bad = intValue >= int.MinValue; // $ Alert
bad = intValue <= int.MaxValue; // $ Alert
good = intValue > int.MinValue;
good = intValue < int.MaxValue;
bad = uintValue >= uint.MinValue;
bad = uintValue >= uint.MinValue; // $ Alert
good = uintValue > uint.MinValue;
bad = ulongValue >= ulong.MinValue;
bad = ulongValue >= ulong.MinValue; // $ Alert
good = ulongValue > ulong.MinValue;
// Explicit casts can cause large values to be truncated or
// to wrap into negative values.
good = (sbyte)byteValue >= 0;
good = (sbyte)byteValue == -1;
bad = (sbyte)byteValue > 127;
bad = (sbyte)byteValue > (sbyte)127;
bad = (sbyte)byteValue > 127; // $ Alert
bad = (sbyte)byteValue > (sbyte)127; // $ Alert
good = (int)uintValue == -1;
good = (sbyte)uintValue == -1;
bad = (sbyte)uintValue == 256;
bad = (sbyte)uintValue == 256; // $ Alert
System.Diagnostics.Debug.Assert(ulongValue >= ulong.MinValue); // GOOD
}

View File

@@ -1,3 +1,29 @@
| ConstantComparison.cs:19:15:19:27 | ... < ... | Condition always evaluates to 'false'. | ConstantComparison.cs:19:15:19:27 | ... < ... | dummy |
| ConstantComparison.cs:20:15:20:27 | ... > ... | Condition always evaluates to 'false'. | ConstantComparison.cs:20:15:20:27 | ... > ... | dummy |
| ConstantComparison.cs:21:15:21:28 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:21:15:21:28 | ... <= ... | dummy |
| ConstantComparison.cs:22:15:22:28 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:22:15:22:28 | ... >= ... | dummy |
| ConstantComparison.cs:24:15:24:29 | ... == ... | Condition always evaluates to 'false'. | ConstantComparison.cs:24:15:24:29 | ... == ... | dummy |
| ConstantComparison.cs:25:15:25:29 | ... != ... | Condition always evaluates to 'true'. | ConstantComparison.cs:25:15:25:29 | ... != ... | dummy |
| ConstantComparison.cs:26:15:26:30 | ... == ... | Condition always evaluates to 'false'. | ConstantComparison.cs:26:15:26:30 | ... == ... | dummy |
| ConstantComparison.cs:27:15:27:30 | ... != ... | Condition always evaluates to 'true'. | ConstantComparison.cs:27:15:27:30 | ... != ... | dummy |
| ConstantComparison.cs:28:15:28:20 | ... != ... | Condition always evaluates to 'true'. | ConstantComparison.cs:28:15:28:20 | ... != ... | dummy |
| ConstantComparison.cs:42:15:42:32 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:42:15:42:32 | ... <= ... | dummy |
| ConstantComparison.cs:43:15:43:28 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:43:15:43:28 | ... >= ... | dummy |
| ConstantComparison.cs:48:15:48:40 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:48:15:48:40 | ... >= ... | dummy |
| ConstantComparison.cs:49:15:49:40 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:49:15:49:40 | ... <= ... | dummy |
| ConstantComparison.cs:54:15:54:42 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:54:15:54:42 | ... >= ... | dummy |
| ConstantComparison.cs:55:15:55:42 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:55:15:55:42 | ... <= ... | dummy |
| ConstantComparison.cs:60:15:60:42 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:60:15:60:42 | ... >= ... | dummy |
| ConstantComparison.cs:61:15:61:42 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:61:15:61:42 | ... <= ... | dummy |
| ConstantComparison.cs:66:15:66:44 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:66:15:66:44 | ... >= ... | dummy |
| ConstantComparison.cs:67:15:67:44 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:67:15:67:44 | ... <= ... | dummy |
| ConstantComparison.cs:72:15:72:38 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:72:15:72:38 | ... >= ... | dummy |
| ConstantComparison.cs:73:15:73:38 | ... <= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:73:15:73:38 | ... <= ... | dummy |
| ConstantComparison.cs:78:15:78:40 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:78:15:78:40 | ... >= ... | dummy |
| ConstantComparison.cs:81:15:81:42 | ... >= ... | Condition always evaluates to 'true'. | ConstantComparison.cs:81:15:81:42 | ... >= ... | dummy |
| ConstantComparison.cs:88:15:88:36 | ... > ... | Condition always evaluates to 'false'. | ConstantComparison.cs:88:15:88:36 | ... > ... | dummy |
| ConstantComparison.cs:89:15:89:43 | ... > ... | Condition always evaluates to 'false'. | ConstantComparison.cs:89:15:89:43 | ... > ... | dummy |
| ConstantComparison.cs:92:15:92:37 | ... == ... | Condition always evaluates to 'false'. | ConstantComparison.cs:92:15:92:37 | ... == ... | dummy |
| ConstantCondition.cs:38:18:38:29 | (...) ... | Expression is always 'null'. | ConstantCondition.cs:38:18:38:29 | (...) ... | dummy |
| ConstantCondition.cs:39:18:39:24 | (...) ... | Expression is never 'null'. | ConstantCondition.cs:39:18:39:24 | (...) ... | dummy |
| ConstantCondition.cs:46:17:46:26 | (...) ... | Expression is always 'null'. | ConstantCondition.cs:46:17:46:26 | (...) ... | dummy |

View File

@@ -1,26 +0,0 @@
| ConstantComparison.cs:19:15:19:27 | ... < ... | This comparison is always false. |
| ConstantComparison.cs:20:15:20:27 | ... > ... | This comparison is always false. |
| ConstantComparison.cs:21:15:21:28 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:22:15:22:28 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:24:15:24:29 | ... == ... | This comparison is always false. |
| ConstantComparison.cs:25:15:25:29 | ... != ... | This comparison is always true. |
| ConstantComparison.cs:26:15:26:30 | ... == ... | This comparison is always false. |
| ConstantComparison.cs:27:15:27:30 | ... != ... | This comparison is always true. |
| ConstantComparison.cs:28:15:28:20 | ... != ... | This comparison is always true. |
| ConstantComparison.cs:42:15:42:32 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:43:15:43:28 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:48:15:48:40 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:49:15:49:40 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:54:15:54:42 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:55:15:55:42 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:60:15:60:42 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:61:15:61:42 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:66:15:66:44 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:67:15:67:44 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:72:15:72:38 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:73:15:73:38 | ... <= ... | This comparison is always true. |
| ConstantComparison.cs:78:15:78:40 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:81:15:81:42 | ... >= ... | This comparison is always true. |
| ConstantComparison.cs:88:15:88:36 | ... > ... | This comparison is always false. |
| ConstantComparison.cs:89:15:89:43 | ... > ... | This comparison is always false. |
| ConstantComparison.cs:92:15:92:37 | ... == ... | This comparison is always false. |

View File

@@ -1 +0,0 @@
Likely Bugs/ConstantComparison.ql

View File

@@ -1,2 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj