mirror of
https://github.com/github/codeql.git
synced 2026-04-11 18:14:01 +02:00
Merge pull request #21599 from aschackmull/csharp/constantcondition-simplify
C#: Simplify the ConstantCondition query.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,7 +41,9 @@ module ConstCondInput implements ConstCond::InputSig<ControlFlow::BasicBlock> {
|
||||
module ConstCondImpl = ConstCond::Make<Location, Cfg, ConstCondInput>;
|
||||
|
||||
predicate nullCheck(Expr e, boolean direct) {
|
||||
exists(QualifiableExpr qe | qe.isConditional() and qe.getQualifier() = e and direct = true)
|
||||
exists(QualifiableExpr qe | qe.isConditional() and direct = true |
|
||||
qe.getQualifier() = e or qe.(ExtensionMethodCall).getArgument(0) = e
|
||||
)
|
||||
or
|
||||
exists(NullCoalescingOperation nce | nce.getLeftOperand() = e and direct = true)
|
||||
or
|
||||
@@ -108,57 +110,14 @@ class ConstantGuard extends ConstantCondition {
|
||||
class ConstantBooleanCondition extends ConstantCondition {
|
||||
boolean b;
|
||||
|
||||
ConstantBooleanCondition() { isConstantCondition(this, b) }
|
||||
ConstantBooleanCondition() { isConstantComparison(this, b) }
|
||||
|
||||
override string getMessage() { result = "Condition always evaluates to '" + b + "'." }
|
||||
|
||||
override predicate isWhiteListed() {
|
||||
// E.g. `x ?? false`
|
||||
this.(BoolLiteral) = any(NullCoalescingOperation nce).getRightOperand() or
|
||||
// No need to flag logical operations when the operands are constant
|
||||
isConstantCondition(this.(LogicalNotExpr).getOperand(), _) or
|
||||
this =
|
||||
any(LogicalAndExpr lae |
|
||||
isConstantCondition(lae.getAnOperand(), false)
|
||||
or
|
||||
isConstantCondition(lae.getLeftOperand(), true) and
|
||||
isConstantCondition(lae.getRightOperand(), true)
|
||||
) or
|
||||
this =
|
||||
any(LogicalOrExpr loe |
|
||||
isConstantCondition(loe.getAnOperand(), true)
|
||||
or
|
||||
isConstantCondition(loe.getLeftOperand(), false) and
|
||||
isConstantCondition(loe.getRightOperand(), false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A constant condition in an `if` statement or a conditional expression. */
|
||||
class ConstantIfCondition extends ConstantBooleanCondition {
|
||||
ConstantIfCondition() {
|
||||
this = any(IfStmt is).getCondition().getAChildExpr*() or
|
||||
this = any(ConditionalExpr ce).getCondition().getAChildExpr*()
|
||||
}
|
||||
|
||||
override predicate isWhiteListed() {
|
||||
ConstantBooleanCondition.super.isWhiteListed()
|
||||
or
|
||||
// It is a common pattern to use a local constant/constant field to control
|
||||
// whether code parts must be executed or not
|
||||
this instanceof AssignableRead and
|
||||
not this instanceof ParameterRead
|
||||
}
|
||||
}
|
||||
|
||||
/** A constant loop condition. */
|
||||
class ConstantLoopCondition extends ConstantBooleanCondition {
|
||||
ConstantLoopCondition() { this = any(LoopStmt ls).getCondition() }
|
||||
|
||||
override predicate isWhiteListed() {
|
||||
// Clearly intentional infinite loops are allowed
|
||||
this.(BoolLiteral).getBoolValue() = true
|
||||
}
|
||||
private Expr getQualifier(QualifiableExpr e) {
|
||||
// `e.getQualifier()` does not work for calls to extension methods
|
||||
result = e.getChildExpr(-1)
|
||||
}
|
||||
|
||||
/** A constant nullness condition. */
|
||||
@@ -166,14 +125,23 @@ class ConstantNullnessCondition extends ConstantCondition {
|
||||
boolean b;
|
||||
|
||||
ConstantNullnessCondition() {
|
||||
forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() |
|
||||
exists(ControlFlow::NullnessSuccessor t, ControlFlow::Node s |
|
||||
s = cfn.getASuccessorByType(t)
|
||||
|
|
||||
b = t.getValue() and
|
||||
not s.isJoin()
|
||||
) and
|
||||
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
|
||||
nullCheck(this, true) and
|
||||
exists(Expr stripped | stripped = this.(Expr).stripCasts() |
|
||||
stripped.getType() =
|
||||
any(ValueType t |
|
||||
not t instanceof NullableType and
|
||||
// Extractor bug: the type of `x?.Length` is reported as `int`, but it should
|
||||
// be `int?`
|
||||
not getQualifier*(stripped).(QualifiableExpr).isConditional()
|
||||
) and
|
||||
b = false
|
||||
or
|
||||
stripped instanceof NullLiteral and
|
||||
b = true
|
||||
or
|
||||
stripped.hasValue() and
|
||||
not stripped instanceof NullLiteral and
|
||||
b = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -184,39 +152,6 @@ class ConstantNullnessCondition extends ConstantCondition {
|
||||
}
|
||||
}
|
||||
|
||||
/** A constant matching condition. */
|
||||
class ConstantMatchingCondition extends ConstantCondition {
|
||||
boolean b;
|
||||
|
||||
ConstantMatchingCondition() {
|
||||
this instanceof Expr and
|
||||
forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() |
|
||||
exists(ControlFlow::MatchingSuccessor t | exists(cfn.getASuccessorByType(t)) |
|
||||
b = t.getValue()
|
||||
) and
|
||||
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isWhiteListed() {
|
||||
exists(Switch se, Case c, int i |
|
||||
c = se.getCase(i) and
|
||||
c.getPattern() = this.(DiscardExpr)
|
||||
|
|
||||
i > 0
|
||||
or
|
||||
i = 0 and
|
||||
exists(Expr cond | c.getCondition() = cond and not isConstantCondition(cond, true))
|
||||
)
|
||||
or
|
||||
this = any(PositionalPatternExpr ppe).getPattern(_)
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
if b = true then result = "Pattern always matches." else result = "Pattern never matches."
|
||||
}
|
||||
}
|
||||
|
||||
from ConstantCondition c, string msg, Guards::Guards::Guard reason, string reasonMsg
|
||||
where
|
||||
msg = c.getMessage() and
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
for (uint order = numberOfOrders; order >= 0; order--)
|
||||
ProcessOrder(order);
|
||||
@@ -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 < 0</code> is always false,</li>
|
||||
<li><code>0 > Unsigned</code> is always false,</li>
|
||||
<li><code>0 ≤ Unsigned</code> is always true,</li>
|
||||
<li><code>Unsigned ≥ 0</code> is always true,</li>
|
||||
<li><code>Unsigned == -1</code> is always false,</li>
|
||||
<li><code>Byte < 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>
|
||||
@@ -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 + "."
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* The `cs/constant-condition` query has been simplified. The query no longer reports trivially constant conditions as they were found to generally be intentional. As a result, it should now produce fewer false positives. Additionally, the simplification means that it now reports all the results that `cs/constant-comparison` used to report, and as consequence, that query has been deleted.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -59,9 +59,9 @@ class ConstantMatching
|
||||
{
|
||||
switch (1 + 2)
|
||||
{
|
||||
case 2: // $ Alert
|
||||
case 2: // Intentionally missing Alert
|
||||
break;
|
||||
case 3: // $ Alert
|
||||
case 3: // Intentionally missing Alert
|
||||
break;
|
||||
case int _: // GOOD
|
||||
break;
|
||||
@@ -72,7 +72,7 @@ class ConstantMatching
|
||||
{
|
||||
switch ((object)s)
|
||||
{
|
||||
case int _: // $ Alert
|
||||
case int _: // Intentionally missing Alert
|
||||
break;
|
||||
case "": // GOOD
|
||||
break;
|
||||
@@ -92,7 +92,7 @@ class ConstantMatching
|
||||
{
|
||||
return o switch
|
||||
{
|
||||
_ => o.ToString() // $ Alert
|
||||
_ => o.ToString() // GOOD, catch-all pattern is fine
|
||||
};
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class ConstantMatching
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case var _: // $ Alert
|
||||
case var _: // GOOD, catch-all pattern is fine
|
||||
return "even";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,47 @@
|
||||
| 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 |
|
||||
| ConstantCondition.cs:47:17:47:18 | "" | Expression is never 'null'. | ConstantCondition.cs:47:17:47:18 | "" | dummy |
|
||||
| ConstantCondition.cs:48:13:48:19 | (...) ... | Expression is never 'null'. | ConstantCondition.cs:48:13:48:19 | (...) ... | dummy |
|
||||
| ConstantCondition.cs:49:13:49:14 | "" | Expression is never 'null'. | ConstantCondition.cs:49:13:49:14 | "" | dummy |
|
||||
| ConstantCondition.cs:62:18:62:18 | 2 | Pattern never matches. | ConstantCondition.cs:62:18:62:18 | 2 | dummy |
|
||||
| ConstantCondition.cs:64:18:64:18 | 3 | Pattern always matches. | ConstantCondition.cs:64:18:64:18 | 3 | dummy |
|
||||
| ConstantCondition.cs:75:18:75:20 | access to type Int32 | Pattern never matches. | ConstantCondition.cs:75:18:75:20 | access to type Int32 | dummy |
|
||||
| ConstantCondition.cs:95:13:95:13 | _ | Pattern always matches. | ConstantCondition.cs:95:13:95:13 | _ | dummy |
|
||||
| ConstantCondition.cs:114:13:114:14 | access to parameter b1 | Condition is always true because of $@. | ConstantCondition.cs:110:14:110:15 | access to parameter b1 | access to parameter b1 |
|
||||
| ConstantCondition.cs:114:19:114:20 | access to parameter b2 | Condition is always true because of $@. | ConstantCondition.cs:112:14:112:15 | access to parameter b2 | access to parameter b2 |
|
||||
| ConstantCondition.cs:141:22:141:22 | _ | Pattern always matches. | ConstantCondition.cs:141:22:141:22 | _ | dummy |
|
||||
| ConstantConditionBad.cs:5:16:5:20 | ... > ... | Condition always evaluates to 'false'. | ConstantConditionBad.cs:5:16:5:20 | ... > ... | dummy |
|
||||
| ConstantConditionalExpressionCondition.cs:11:22:11:34 | ... == ... | Condition always evaluates to 'true'. | ConstantConditionalExpressionCondition.cs:11:22:11:34 | ... == ... | dummy |
|
||||
| ConstantConditionalExpressionCondition.cs:12:21:12:25 | false | Condition always evaluates to 'false'. | ConstantConditionalExpressionCondition.cs:12:21:12:25 | false | dummy |
|
||||
| ConstantConditionalExpressionCondition.cs:13:21:13:30 | ... == ... | Condition always evaluates to 'true'. | ConstantConditionalExpressionCondition.cs:13:21:13:30 | ... == ... | dummy |
|
||||
| ConstantForCondition.cs:9:29:9:33 | false | Condition always evaluates to 'false'. | ConstantForCondition.cs:9:29:9:33 | false | dummy |
|
||||
| ConstantDoCondition.cs:15:22:15:34 | ... == ... | Condition always evaluates to 'true'. | ConstantDoCondition.cs:15:22:15:34 | ... == ... | dummy |
|
||||
| ConstantDoCondition.cs:32:22:32:31 | ... == ... | Condition always evaluates to 'true'. | ConstantDoCondition.cs:32:22:32:31 | ... == ... | dummy |
|
||||
| ConstantForCondition.cs:11:29:11:34 | ... == ... | Condition always evaluates to 'false'. | ConstantForCondition.cs:11:29:11:34 | ... == ... | dummy |
|
||||
| ConstantIfCondition.cs:11:17:11:29 | ... == ... | Condition always evaluates to 'true'. | ConstantIfCondition.cs:11:17:11:29 | ... == ... | dummy |
|
||||
| ConstantIfCondition.cs:14:17:14:21 | false | Condition always evaluates to 'false'. | ConstantIfCondition.cs:14:17:14:21 | false | dummy |
|
||||
| ConstantIfCondition.cs:17:17:17:26 | ... == ... | Condition always evaluates to 'true'. | ConstantIfCondition.cs:17:17:17:26 | ... == ... | dummy |
|
||||
| ConstantIsNullOrEmpty.cs:10:21:10:54 | call to method IsNullOrEmpty | Condition always evaluates to 'false'. | ConstantIsNullOrEmpty.cs:10:21:10:54 | call to method IsNullOrEmpty | dummy |
|
||||
| ConstantIsNullOrEmpty.cs:46:21:46:46 | call to method IsNullOrEmpty | Condition always evaluates to 'true'. | ConstantIsNullOrEmpty.cs:46:21:46:46 | call to method IsNullOrEmpty | dummy |
|
||||
| ConstantIsNullOrEmpty.cs:50:21:50:44 | call to method IsNullOrEmpty | Condition always evaluates to 'true'. | ConstantIsNullOrEmpty.cs:50:21:50:44 | call to method IsNullOrEmpty | dummy |
|
||||
| ConstantIsNullOrEmpty.cs:54:21:54:45 | call to method IsNullOrEmpty | Condition always evaluates to 'false'. | ConstantIsNullOrEmpty.cs:54:21:54:45 | call to method IsNullOrEmpty | dummy |
|
||||
| ConstantIfCondition.cs:35:20:35:25 | ... >= ... | Condition always evaluates to 'true'. | ConstantIfCondition.cs:35:20:35:25 | ... >= ... | dummy |
|
||||
| ConstantNullCoalescingLeftHandOperand.cs:11:24:11:34 | access to constant NULL_OBJECT | Expression is never 'null'. | ConstantNullCoalescingLeftHandOperand.cs:11:24:11:34 | access to constant NULL_OBJECT | dummy |
|
||||
| ConstantNullCoalescingLeftHandOperand.cs:12:24:12:27 | null | Expression is always 'null'. | ConstantNullCoalescingLeftHandOperand.cs:12:24:12:27 | null | dummy |
|
||||
| ConstantWhileCondition.cs:12:20:12:32 | ... == ... | Condition always evaluates to 'true'. | ConstantWhileCondition.cs:12:20:12:32 | ... == ... | dummy |
|
||||
| ConstantWhileCondition.cs:16:20:16:24 | false | Condition always evaluates to 'false'. | ConstantWhileCondition.cs:16:20:16:24 | false | dummy |
|
||||
| ConstantWhileCondition.cs:24:20:24:29 | ... == ... | Condition always evaluates to 'true'. | ConstantWhileCondition.cs:24:20:24:29 | ... == ... | dummy |
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ConstantConditionalExpression
|
||||
public void Foo()
|
||||
{
|
||||
int i = (ZERO == 1 - 1) ? 0 : 1; // $ Alert
|
||||
int j = false ? 0 : 1; // $ Alert
|
||||
int j = false ? 0 : 1; // GOOD, literal false is likely intentional
|
||||
int k = " " == " " ? 0 : 1; // $ Alert
|
||||
int l = (" "[0] == ' ') ? 0 : 1; // Missing Alert
|
||||
int m = Bar() == 0 ? 0 : 1; // GOOD
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace ConstantDoCondition
|
||||
do
|
||||
{
|
||||
break;
|
||||
} while (ZERO == 1 - 1); // BAD
|
||||
} while (ZERO == 1 - 1); // $ Alert
|
||||
do
|
||||
{
|
||||
break;
|
||||
@@ -29,7 +29,7 @@ namespace ConstantDoCondition
|
||||
do
|
||||
{
|
||||
break;
|
||||
} while (" " == " "); // BAD
|
||||
} while (" " == " "); // $ Alert
|
||||
do
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace ConstantForCondition
|
||||
{
|
||||
public void M()
|
||||
{
|
||||
for (int i = 0; false; i++) // $ Alert
|
||||
for (int i = 0; false; i++) // GOOD, literal false is likely intentional
|
||||
;
|
||||
for (int i = 0; 0 == 1; i++) // $ Alert
|
||||
;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace ConstantIfCondition
|
||||
if (ZERO == 1 - 1) // $ Alert
|
||||
{
|
||||
}
|
||||
if (false) // $ Alert
|
||||
if (false) // GOOD
|
||||
{
|
||||
}
|
||||
if (" " == " ") // $ Alert
|
||||
@@ -30,6 +30,11 @@ namespace ConstantIfCondition
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
public void UnsignedCheck(byte n)
|
||||
{
|
||||
while (n >= 0) { n--; } // $ Alert
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,10 @@ namespace ConstantIsNullOrEmpty
|
||||
static void Main(string[] args)
|
||||
{
|
||||
{
|
||||
if (string.IsNullOrEmpty(nameof(args))) // $ Alert
|
||||
// All of the IsNullOrEmpty constant checks have been descoped
|
||||
// from the query as it didn't seem worth the effort to keep them.
|
||||
|
||||
if (string.IsNullOrEmpty(nameof(args))) // Missing Alert (always false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,15 +46,15 @@ namespace ConstantIsNullOrEmpty
|
||||
{
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(null)) // $ Alert
|
||||
if (string.IsNullOrEmpty(null)) // Missing Alert
|
||||
{
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty("")) // $ Alert
|
||||
if (string.IsNullOrEmpty("")) // Missing Alert
|
||||
{
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(" ")) // $ Alert
|
||||
if (string.IsNullOrEmpty(" ")) // Missing Alert
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace ConstantWhileCondition
|
||||
{
|
||||
break;
|
||||
}
|
||||
while (false) // $ Alert
|
||||
while (false) // Silly, but likely intentional
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -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. |
|
||||
@@ -1 +0,0 @@
|
||||
Likely Bugs/ConstantComparison.ql
|
||||
@@ -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
|
||||
@@ -12,7 +12,7 @@ class ConstantMatching
|
||||
void M1()
|
||||
{
|
||||
var c1 = new C1();
|
||||
if (c1.Prop is int) // $ Alert
|
||||
if (c1.Prop is int) // Descoped, no longer reported by the query.
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
| ConstantCondition.cs:15:13:15:26 | ... is ... | Condition always evaluates to 'false'. | ConstantCondition.cs:15:13:15:26 | ... is ... | dummy |
|
||||
| ConstantCondition.cs:15:24:15:26 | access to type Int32 | Pattern never matches. | ConstantCondition.cs:15:24:15:26 | access to type Int32 | dummy |
|
||||
|
||||
Reference in New Issue
Block a user