mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #355 from hvitved/csharp/guards-logic
Approved by calumgrant
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.StructuralComparison
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
import semmle.code.csharp.controlflow.Guards as G
|
||||
|
||||
class SameElement extends StructuralComparisonConfiguration
|
||||
{
|
||||
@@ -22,7 +22,7 @@ class SameElement extends StructuralComparisonConfiguration
|
||||
exists(MethodCall mc, IndexerRead access |
|
||||
mc.getTarget().hasName("ContainsKey")
|
||||
and
|
||||
access.getQualifier().(GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _)
|
||||
access.getQualifier().(G::GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _)
|
||||
and
|
||||
e1 = mc.getArgument(0)
|
||||
and
|
||||
|
||||
@@ -16,4 +16,4 @@ import semmle.code.csharp.security.dataflow.ZipSlip::ZipSlip
|
||||
|
||||
from TaintTrackingConfiguration zipTaintTracking, DataFlow::Node source, DataFlow::Node sink
|
||||
where zipTaintTracking.hasFlow(source, sink)
|
||||
select sink, "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", source, "item path"
|
||||
select sink, "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", source, "item path"
|
||||
|
||||
@@ -9,4 +9,4 @@ class Bad
|
||||
string destFileName = Path.Combine(destDirectory, entry.FullName);
|
||||
entry.ExtractToFile(destFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
/**
|
||||
* Generates C# stubs for use in test code.
|
||||
*
|
||||
* Extend the abstract class `GeneratedDeclaration` with the declarations that should be generated.
|
||||
* This will generate stubs for all the required dependencies as well.
|
||||
*
|
||||
*
|
||||
* Use
|
||||
* ```
|
||||
* select generatedCode()
|
||||
@@ -104,7 +104,7 @@ private abstract class GeneratedType extends ValueOrRefType, GeneratedElement {
|
||||
result = this.stubComment() +
|
||||
this.stubAttributes() +
|
||||
this.stubAbstractModifier() +
|
||||
this.stubStaticModifier() +
|
||||
this.stubStaticModifier() +
|
||||
this.stubAccessibilityModifier() +
|
||||
this.stubKeyword() + " " +
|
||||
this.getUndecoratedName() +
|
||||
|
||||
@@ -144,7 +144,7 @@ class ForwarderAssertMethod extends AssertMethod {
|
||||
override ExceptionClass getExceptionClass() {
|
||||
result = this.getUnderlyingAssertMethod().getExceptionClass()
|
||||
}
|
||||
|
||||
|
||||
/** Gets the underlying assertion method that is being forwarded to. */
|
||||
AssertMethod getUnderlyingAssertMethod() { result = a.getAssertMethod() }
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ abstract class StructuralComparisonConfiguration extends string {
|
||||
*/
|
||||
module Internal {
|
||||
// Import all uses of the internal library to make sure caching works
|
||||
private import semmle.code.csharp.controlflow.Guards
|
||||
private import semmle.code.csharp.controlflow.Guards as G
|
||||
|
||||
/**
|
||||
* A configuration for performing structural comparisons of program elements
|
||||
|
||||
@@ -524,6 +524,7 @@ class ConditionBlock extends BasicBlock {
|
||||
//
|
||||
// In the former case, `x` and `y` control `A`, in the latter case
|
||||
// only `x & y` controls `A` if we do not take sub conditions into account.
|
||||
deprecated
|
||||
predicate controlsSubCond(BasicBlock controlled, boolean testIsTrue, Expr cond, boolean condIsTrue) {
|
||||
impliesSub(getLastNode().getElement(), cond, testIsTrue, condIsTrue) and
|
||||
controls(controlled, any(BooleanSuccessor s | s.getValue() = testIsTrue))
|
||||
@@ -542,6 +543,7 @@ class ConditionBlock extends BasicBlock {
|
||||
* Holds if `e2` is a sub expression of (Boolean) expression `e1`, and
|
||||
* if `e1` has value `b1` then `e2` must have value `b2`.
|
||||
*/
|
||||
deprecated
|
||||
private predicate impliesSub(Expr e1, Expr e2, boolean b1, boolean b2) {
|
||||
if e1 instanceof LogicalNotExpr then (
|
||||
impliesSub(e1.(LogicalNotExpr).getOperand(), e2, b1.booleanNot(), b2)
|
||||
|
||||
@@ -430,12 +430,20 @@ private predicate mustHaveMatchingCompletion(ControlFlowElement cfe) {
|
||||
cfe instanceof SpecificCatchClause
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cfe` is the element inside foreach statement `fs` that has the emptiness
|
||||
* completion.
|
||||
*/
|
||||
predicate foreachEmptiness(ForeachStmt fs, ControlFlowElement cfe) {
|
||||
cfe = fs // use `foreach` statement itself to represent the emptiness test
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a normal completion of `cfe` must be an emptiness completion. Thats is,
|
||||
* whether `cfe` determines whether to execute the body of a `foreach` statement.
|
||||
*/
|
||||
private predicate mustHaveEmptinessCompletion(ControlFlowElement cfe) {
|
||||
cfe instanceof ForeachStmt // use `foreach` statement itself to represent the emptiness test
|
||||
foreachEmptiness(_, cfe)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2593,6 +2593,15 @@ module ControlFlow {
|
||||
this = TPhiPreSsaDef(_, result)
|
||||
}
|
||||
|
||||
LocalScopeVariableRead getARead() {
|
||||
firstReadSameVar(this, result)
|
||||
or
|
||||
exists(LocalScopeVariableRead read |
|
||||
firstReadSameVar(this, read) |
|
||||
adjacentReadPairSameVar+(read, result)
|
||||
)
|
||||
}
|
||||
|
||||
Location getLocation() {
|
||||
exists(AssignableDefinition def |
|
||||
this = TExplicitPreSsaDef(_, _, def, _) |
|
||||
@@ -2720,21 +2729,29 @@ module ControlFlow {
|
||||
ssaRefRank(bb2, i2, v, _) = 1
|
||||
}
|
||||
|
||||
predicate firstReadSameVar(Definition def, LocalScopeVariableRead read) {
|
||||
exists(SimpleLocalScopeVariable v, PreBasicBlock b1, int i1, PreBasicBlock b2, int i2 |
|
||||
adjacentVarRefs(v, b1, i1, b2, i2) and
|
||||
defAt(b1, i1, def, v) and
|
||||
readAt(b2, i2, read, v)
|
||||
)
|
||||
}
|
||||
private cached module PreSsaCached {
|
||||
cached
|
||||
predicate firstReadSameVar(Definition def, LocalScopeVariableRead read) {
|
||||
exists(SimpleLocalScopeVariable v, PreBasicBlock b1, int i1, PreBasicBlock b2, int i2 |
|
||||
adjacentVarRefs(v, b1, i1, b2, i2) and
|
||||
defAt(b1, i1, def, v) and
|
||||
readAt(b2, i2, read, v)
|
||||
)
|
||||
}
|
||||
|
||||
predicate adjacentReadPairSameVar(LocalScopeVariableRead read1, LocalScopeVariableRead read2) {
|
||||
exists(SimpleLocalScopeVariable v, PreBasicBlock bb1, int i1, PreBasicBlock bb2, int i2 |
|
||||
adjacentVarRefs(v, bb1, i1, bb2, i2) and
|
||||
readAt(bb1, i1, read1, v) and
|
||||
readAt(bb2, i2, read2, v)
|
||||
)
|
||||
cached
|
||||
predicate adjacentReadPairSameVar(LocalScopeVariableRead read1, LocalScopeVariableRead read2) {
|
||||
exists(SimpleLocalScopeVariable v, PreBasicBlock bb1, int i1, PreBasicBlock bb2, int i2 |
|
||||
adjacentVarRefs(v, bb1, i1, bb2, i2) and
|
||||
readAt(bb1, i1, read1, v) and
|
||||
readAt(bb2, i2, read2, v)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate forceCachingInSameStage() { any() }
|
||||
}
|
||||
import PreSsaCached
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3327,11 +3344,7 @@ module ControlFlow {
|
||||
* Holds if condition `cb` is a read of the SSA variable in this split.
|
||||
*/
|
||||
private predicate defCondition(ConditionBlock cb) {
|
||||
exists(LocalScopeVariableRead read1, LocalScopeVariableRead read2 |
|
||||
firstReadSameVar(def, read1) |
|
||||
adjacentReadPairSameVar*(read1, read2) and
|
||||
read2 = cb.getLastElement()
|
||||
)
|
||||
cb.getLastElement() = def.getARead()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3827,6 +3840,7 @@ module ControlFlow {
|
||||
cached
|
||||
newtype TPreSsaDef =
|
||||
TExplicitPreSsaDef(PreBasicBlocks::PreBasicBlock bb, int i, AssignableDefinition def, LocalScopeVariable v) {
|
||||
PreSsa::forceCachingInSameStage() and
|
||||
PreSsa::assignableDefAt(bb, i, def, v)
|
||||
}
|
||||
or
|
||||
|
||||
@@ -3,11 +3,273 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import BasicBlocks
|
||||
private import ControlFlow::SuccessorTypes
|
||||
private import semmle.code.csharp.commons.ComparisonTest
|
||||
private import semmle.code.csharp.commons.StructuralComparison::Internal
|
||||
private import semmle.code.csharp.controlflow.BasicBlocks
|
||||
private import semmle.code.csharp.controlflow.Completion
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
|
||||
/** An abstract value. */
|
||||
abstract class AbstractValue extends TAbstractValue {
|
||||
/** Holds if taking the `s` branch out of `cfe` implies that `e` has this value. */
|
||||
abstract predicate branchImplies(ControlFlowElement cfe, ConditionalSuccessor s, Expr e);
|
||||
|
||||
/** Gets a textual representation of this abstract value. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** Provides different types of `AbstractValues`s. */
|
||||
module AbstractValues {
|
||||
/** A Boolean value. */
|
||||
class BooleanValue extends AbstractValue, TBooleanValue {
|
||||
/** Gets the underlying Boolean value. */
|
||||
boolean getValue() { this = TBooleanValue(result) }
|
||||
|
||||
override predicate branchImplies(ControlFlowElement cfe, ConditionalSuccessor s, Expr e) {
|
||||
s.(BooleanSuccessor).getValue() = this.getValue() and
|
||||
exists(BooleanCompletion c |
|
||||
s.matchesCompletion(c) |
|
||||
c.isValidFor(cfe) and
|
||||
e = cfe
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = this.getValue().toString() }
|
||||
}
|
||||
|
||||
/** A value that is either `null` or non-`null`. */
|
||||
class NullValue extends AbstractValue, TNullValue {
|
||||
/** Holds if this value represents `null`. */
|
||||
predicate isNull() { this = TNullValue(true) }
|
||||
|
||||
override predicate branchImplies(ControlFlowElement cfe, ConditionalSuccessor s, Expr e) {
|
||||
this = TNullValue(s.(NullnessSuccessor).getValue()) and
|
||||
exists(NullnessCompletion c |
|
||||
s.matchesCompletion(c) |
|
||||
c.isValidFor(cfe) and
|
||||
e = cfe
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
if this.isNull() then result = "null" else result = "non-null"
|
||||
}
|
||||
}
|
||||
|
||||
/** A value that represents match or non-match against a specific `case` statement. */
|
||||
class MatchValue extends AbstractValue, TMatchValue {
|
||||
/** Gets the case statement. */
|
||||
CaseStmt getCaseStmt() { this = TMatchValue(result, _) }
|
||||
|
||||
/** Holds if this value represents a match. */
|
||||
predicate isMatch() { this = TMatchValue(_, true) }
|
||||
|
||||
override predicate branchImplies(ControlFlowElement cfe, ConditionalSuccessor s, Expr e) {
|
||||
this = TMatchValue(_, s.(MatchingSuccessor).getValue()) and
|
||||
exists(MatchingCompletion c, SwitchStmt ss, CaseStmt cs |
|
||||
s.matchesCompletion(c) |
|
||||
c.isValidFor(cfe) and
|
||||
switchMatching(ss, cs, cfe) and
|
||||
e = ss.getCondition() and
|
||||
cs = this.getCaseStmt()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(string s |
|
||||
s = this.getCaseStmt().toString() |
|
||||
if this.isMatch() then result = "match " + s else result = "non-match " + s
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A value that represents an empty or non-empty collection. */
|
||||
class EmptyCollectionValue extends AbstractValue, TEmptyCollectionValue {
|
||||
/** Holds if this value represents an empty collection. */
|
||||
predicate isEmpty() { this = TEmptyCollectionValue(true) }
|
||||
|
||||
override predicate branchImplies(ControlFlowElement cfe, ConditionalSuccessor s, Expr e) {
|
||||
this = TEmptyCollectionValue(s.(EmptinessSuccessor).getValue()) and
|
||||
exists(EmptinessCompletion c, ForeachStmt fs |
|
||||
s.matchesCompletion(c) |
|
||||
c.isValidFor(cfe) and
|
||||
foreachEmptiness(fs, cfe) and
|
||||
e = fs.getIterableExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
if this.isEmpty() then result = "empty" else result = "non-empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
private import AbstractValues
|
||||
|
||||
/**
|
||||
* An expression that evaluates to a value that can be dereferenced. That is,
|
||||
* an expression that may evaluate to `null`.
|
||||
*/
|
||||
class DereferenceableExpr extends Expr {
|
||||
DereferenceableExpr() {
|
||||
exists(Expr e, Type t |
|
||||
// There is currently a bug in the extractor: the type of `x?.Length` is
|
||||
// incorrectly `int`, while it should have been `int?`. We apply
|
||||
// `getNullEquivParent()` as a workaround
|
||||
this = getNullEquivParent*(e) and
|
||||
t = e.getType() |
|
||||
t instanceof NullableType
|
||||
or
|
||||
t instanceof RefType
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that directly tests whether this expression is `null`.
|
||||
*
|
||||
* If the returned expression evaluates to `v`, then this expression is
|
||||
* guaranteed to be `null` if `isNull` is true, and non-`null` if `isNull` is
|
||||
* false.
|
||||
*
|
||||
* For example, if the expression `x != null` evaluates to `true` then the
|
||||
* expression `x` is guaranteed to be non-`null`.
|
||||
*/
|
||||
private Expr getABooleanNullCheck(BooleanValue v, boolean isNull) {
|
||||
exists(boolean branch |
|
||||
branch = v.getValue() |
|
||||
// Comparison with `null`, for example `x != null`
|
||||
exists(ComparisonTest ct, ComparisonKind ck, NullLiteral nl |
|
||||
ct.getExpr() = result and
|
||||
ct.getAnArgument() = this and
|
||||
ct.getAnArgument() = nl and
|
||||
this != nl and
|
||||
ck = ct.getComparisonKind() |
|
||||
ck.isEquality() and isNull = branch
|
||||
or
|
||||
ck.isInequality() and isNull = branch.booleanNot()
|
||||
)
|
||||
or
|
||||
// Comparison with a non-`null` value, for example `x?.Length > 0`
|
||||
exists(ComparisonTest ct, ComparisonKind ck, Expr e |
|
||||
ct.getExpr() = result |
|
||||
ct.getAnArgument() = this and
|
||||
ct.getAnArgument() = e and
|
||||
nonNullValue(e) and
|
||||
ck = ct.getComparisonKind() and
|
||||
this != e and
|
||||
isNull = false and
|
||||
if ck.isInequality() then branch = false else branch = true
|
||||
)
|
||||
or
|
||||
// Call to `string.IsNullOrEmpty()`
|
||||
result = any(MethodCall mc |
|
||||
mc.getTarget() = any(SystemStringClass c).getIsNullOrEmptyMethod() and
|
||||
mc.getArgument(0) = this and
|
||||
branch = false and
|
||||
isNull = false
|
||||
)
|
||||
or
|
||||
result = any(IsExpr ie |
|
||||
ie.getExpr() = this and
|
||||
if ie.(IsConstantExpr).getConstant() instanceof NullLiteral then
|
||||
// E.g. `x is null`
|
||||
isNull = branch
|
||||
else
|
||||
// E.g. `x is string` or `x is ""`
|
||||
(branch = true and isNull = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that tests via matching whether this expression is `null`.
|
||||
*
|
||||
* If the returned element matches (`v.isMatch()`) or non-matches
|
||||
* (`not v.isMatch()`), then this expression is guaranteed to be `null`
|
||||
* if `isNull` is true, and non-`null` if `isNull` is false.
|
||||
*
|
||||
* For example, if the case statement `case string s` matches in
|
||||
*
|
||||
* ```
|
||||
* switch (o)
|
||||
* {
|
||||
* case string s:
|
||||
* return s;
|
||||
* default:
|
||||
* return "";
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* then `o` is guaranteed to be non-`null`.
|
||||
*/
|
||||
private Expr getAMatchingNullCheck(MatchValue v, boolean isNull) {
|
||||
exists(SwitchStmt ss, CaseStmt cs |
|
||||
cs = v.getCaseStmt() and
|
||||
this = ss.getCondition() and
|
||||
result = this and
|
||||
cs = ss.getACase() |
|
||||
// E.g. `case string`
|
||||
cs instanceof TypeCase and
|
||||
v.isMatch() and
|
||||
isNull = false
|
||||
or
|
||||
cs = any(ConstCase cc |
|
||||
if cc.getExpr() instanceof NullLiteral then
|
||||
// `case null`
|
||||
if v.isMatch() then isNull = true else isNull = false
|
||||
else (
|
||||
// E.g. `case ""`
|
||||
v.isMatch() and
|
||||
isNull = false
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that tests via nullness whether this expression is `null`.
|
||||
*
|
||||
* If the returned expression evaluates to `null` (`v.isNull()`) or evaluates to
|
||||
* non-`null` (`not v.isNull()`), then this expression is guaranteed to be `null`
|
||||
* if `isNull` is true, and non-`null` if `isNull` is false.
|
||||
*
|
||||
* For example, if `x` evaluates to `null` in `x ?? y` then `y` is evaluated, and
|
||||
* `x` is guaranteed to be `null`.
|
||||
*/
|
||||
private Expr getANullnessNullCheck(NullValue v, boolean isNull) {
|
||||
exists(NullnessCompletion c |
|
||||
c.isValidFor(this) |
|
||||
result = this and
|
||||
if c.isNull() then (
|
||||
v.isNull() and
|
||||
isNull = true
|
||||
)
|
||||
else (
|
||||
not v.isNull() and
|
||||
isNull = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that tests whether this expression is `null`.
|
||||
*
|
||||
* If the returned expression has abstract value `v`, then this expression is
|
||||
* guaranteed to be `null` if `isNull` is true, and non-`null` if `isNull` is
|
||||
* false.
|
||||
*
|
||||
* For example, if the expression `x != null` evaluates to `true` then the
|
||||
* expression `x` is guaranteed to be non-`null`.
|
||||
*/
|
||||
Expr getANullCheck(AbstractValue v, boolean isNull) {
|
||||
result = this.getABooleanNullCheck(v, isNull)
|
||||
or
|
||||
result = this.getAMatchingNullCheck(v, isNull)
|
||||
or
|
||||
result = this.getANullnessNullCheck(v, isNull)
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that accesses/calls a declaration. */
|
||||
class AccessOrCallExpr extends Expr {
|
||||
private Declaration target;
|
||||
@@ -61,12 +323,11 @@ private AssignableRead getATrackedRead(Ssa::Definition def) {
|
||||
/**
|
||||
* A guarded expression.
|
||||
*
|
||||
* A guarded expression is an access or a call that is reached only
|
||||
* when a conditional containing a structurally equal expression
|
||||
* evaluates to one of `true` or `false`.
|
||||
* A guarded expression is an access or a call that is reached only when another
|
||||
* expression, `e`, has a certain abstract value, where `e` contains a sub
|
||||
* expression that is structurally equal to this expression.
|
||||
*
|
||||
* For example, the property call `x.Field.Property` on line 3 is
|
||||
* guarded in
|
||||
* For example, the property call `x.Field.Property` on line 3 is guarded in
|
||||
*
|
||||
* ```
|
||||
* string M(C x) {
|
||||
@@ -97,234 +358,77 @@ private AssignableRead getATrackedRead(Ssa::Definition def) {
|
||||
* definition).
|
||||
*/
|
||||
class GuardedExpr extends AccessOrCallExpr {
|
||||
private Expr cond0;
|
||||
private AccessOrCallExpr e0;
|
||||
private boolean b0;
|
||||
|
||||
GuardedExpr() {
|
||||
Internal::isGuardedBy(this, cond0, e0, b0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this expression is guarded by expression `cond`, which must
|
||||
* evaluate to `b`. The expression `e` is a sub expression of `cond`
|
||||
* that is structurally equal to this expression.
|
||||
*
|
||||
* In case this expression or `e` accesses an SSA variable in its
|
||||
* left-most qualifier, then so must the other (accessing the same SSA
|
||||
* variable).
|
||||
*/
|
||||
predicate isGuardedBy(Expr cond, Expr e, boolean b) {
|
||||
cond = cond0 and
|
||||
e = e0 and
|
||||
b = b0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A nullness guarded expression.
|
||||
*
|
||||
* A nullness guarded expression is an access or a call that is reached only
|
||||
* when a nullness condition containing a structurally equal expression
|
||||
* evaluates to one of `null` or non-`null`.
|
||||
*
|
||||
* For example, the second access to `x` is only evaluated when `x` is null
|
||||
* in
|
||||
*
|
||||
* ```
|
||||
* string M(string x) => x ?? x;
|
||||
* ```
|
||||
*/
|
||||
class NullnessGuardedExpr extends AccessOrCallExpr {
|
||||
private Expr e0;
|
||||
private boolean isNull0;
|
||||
private AccessOrCallExpr sub0;
|
||||
private AbstractValue v0;
|
||||
|
||||
NullnessGuardedExpr() {
|
||||
Internal::isGuardedByNullness(this, e0, isNull0)
|
||||
GuardedExpr() { isGuardedBy(this, e0, sub0, v0) }
|
||||
|
||||
/**
|
||||
* Gets an expression that guards this expression. That is, this expression is
|
||||
* only reached when the returned expression has abstract value `v`.
|
||||
*
|
||||
* The expression `sub` is a sub expression of the guarding expression that is
|
||||
* structurally equal to this expression.
|
||||
*
|
||||
* In case this expression or `sub` accesses an SSA variable in its
|
||||
* left-most qualifier, then so must the other (accessing the same SSA
|
||||
* variable).
|
||||
*/
|
||||
Expr getAGuard(Expr sub, AbstractValue v) {
|
||||
result = e0 and
|
||||
sub = sub0 and
|
||||
v = v0
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this expression is guarded by expression `cond`, which must
|
||||
* evaluate to `b`. The expression `e` is a sub expression of `cond`
|
||||
* evaluate to `b`. The expression `sub` is a sub expression of `cond`
|
||||
* that is structurally equal to this expression.
|
||||
*
|
||||
* In case this expression or `e` accesses an SSA variable in its
|
||||
* In case this expression or `sub` accesses an SSA variable in its
|
||||
* left-most qualifier, then so must the other (accessing the same SSA
|
||||
* variable).
|
||||
*/
|
||||
predicate isGuardedBy(Expr e, boolean isNull) {
|
||||
e = e0 and
|
||||
isNull = isNull0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A matching guarded expression.
|
||||
*
|
||||
* A matching guarded expression is an access or a call that is reached only
|
||||
* when a pattern, matching against a structurally equal expression, matches
|
||||
* or non-matches.
|
||||
*
|
||||
* For example, the access to `o` on line 8 is only evaluated when `case null`
|
||||
* does not match.
|
||||
*
|
||||
* ```
|
||||
* string M(object o)
|
||||
* {
|
||||
* switch (o)
|
||||
* {
|
||||
* case null:
|
||||
* return "";
|
||||
* default:
|
||||
* return o.ToString();
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class MatchingGuardedExpr extends AccessOrCallExpr {
|
||||
private AccessOrCallExpr e0;
|
||||
private CaseStmt cs0;
|
||||
private boolean isMatch0;
|
||||
|
||||
MatchingGuardedExpr() {
|
||||
Internal::isGuardedByMatching(this, e0, cs0, isMatch0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this expression is guarded by case statement `cs` matching
|
||||
* (`isMatch = true`) or non-matching (`isMatch = false`). The expression
|
||||
* `e` is structurally equal to this expression being matched against in
|
||||
* `cs`.
|
||||
*
|
||||
* In case this expression or `e` accesses an SSA variable in its
|
||||
* left-most qualifier, then so must the other (accessing the same SSA
|
||||
* variable).
|
||||
*/
|
||||
predicate isGuardedBy(AccessOrCallExpr e, CaseStmt cs, boolean isMatch) {
|
||||
e = e0 and
|
||||
cs0 = cs and
|
||||
isMatch0 = isMatch
|
||||
predicate isGuardedBy(Expr cond, Expr sub, boolean b) {
|
||||
cond = this.getAGuard(sub, any(BooleanValue v | v.getValue() = b))
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression guarded by a `null` check. */
|
||||
class NullGuardedExpr extends AccessOrCallExpr {
|
||||
class NullGuardedExpr extends GuardedExpr {
|
||||
NullGuardedExpr() {
|
||||
this.getType() instanceof RefType and
|
||||
exists(Expr cond, Expr sub, boolean b |
|
||||
this.(GuardedExpr).isGuardedBy(cond, sub, b) |
|
||||
// Comparison with `null`, for example `x != null`
|
||||
exists(ComparisonTest ct, ComparisonKind ck |
|
||||
ct.getExpr() = cond and
|
||||
ct.getAnArgument() = Internal::getNullEquivParent*(sub) and
|
||||
ct.getAnArgument() instanceof NullLiteral and
|
||||
ck = ct.getComparisonKind() |
|
||||
ck.isEquality() and b = false
|
||||
or
|
||||
ck.isInequality() and b = true
|
||||
)
|
||||
or
|
||||
// Comparison with a non-`null` value, for example `x?.Length > 0`
|
||||
exists(ComparisonTest ct, ComparisonKind ck, Type t |
|
||||
ct.getExpr() = cond and
|
||||
ct.getAnArgument() = Internal::getNullEquivParent*(sub) and
|
||||
sub.getType() = t and
|
||||
(t instanceof RefType or t instanceof NullableType) and
|
||||
Internal::nonNullValue(ct.getAnArgument()) and
|
||||
ck = ct.getComparisonKind() |
|
||||
if ck.isInequality() then b = false else b = true
|
||||
)
|
||||
or
|
||||
// Call to `string.IsNullOrEmpty()`
|
||||
cond = any(MethodCall mc |
|
||||
mc.getTarget() = any(SystemStringClass c).getIsNullOrEmptyMethod() and
|
||||
mc.getArgument(0) = sub and
|
||||
b = false
|
||||
)
|
||||
or
|
||||
cond = any(IsExpr ie |
|
||||
ie.getExpr() = sub and
|
||||
if ie.(IsConstantExpr).getConstant() instanceof NullLiteral then
|
||||
// E.g. `x is null`
|
||||
b = false
|
||||
else
|
||||
// E.g. `x is string`
|
||||
b = true
|
||||
)
|
||||
)
|
||||
or
|
||||
this.(NullnessGuardedExpr).isGuardedBy(_, false)
|
||||
or
|
||||
exists(CaseStmt cs, boolean isMatch |
|
||||
this.(MatchingGuardedExpr).isGuardedBy(_, cs, isMatch) |
|
||||
// E.g. `case string`
|
||||
cs instanceof TypeCase and
|
||||
isMatch = true
|
||||
or
|
||||
cs = any(ConstCase cc |
|
||||
if cc.getExpr() instanceof NullLiteral then
|
||||
// `case null`
|
||||
isMatch = false
|
||||
else
|
||||
// E.g. `case ""`
|
||||
isMatch = true
|
||||
)
|
||||
)
|
||||
exists(Expr e, NullValue v | e = this.getAGuard(e, v) | not v.isNull())
|
||||
}
|
||||
}
|
||||
|
||||
private module Internal {
|
||||
private import semmle.code.csharp.controlflow.Completion
|
||||
private import ControlFlow::SuccessorTypes
|
||||
/** INTERNAL: Do not use. */
|
||||
module Internal {
|
||||
private import ControlFlow::Internal
|
||||
|
||||
private cached module Cached {
|
||||
cached predicate isGuardedBy(AccessOrCallExpr guarded, Expr cond, AccessOrCallExpr e, boolean b) {
|
||||
exists(BasicBlock bb |
|
||||
controls(cond, e, bb, b) and
|
||||
bb = guarded.getAControlFlowNode().getBasicBlock() and
|
||||
exists(ConditionOnExprComparisonConfig c | c.same(e, guarded)) |
|
||||
not guarded.hasSsaQualifier() and not e.hasSsaQualifier()
|
||||
or
|
||||
guarded.getSsaQualifier() = e.getSsaQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate isGuardedByNullness(AccessOrCallExpr guarded, AccessOrCallExpr e, boolean isNull) {
|
||||
exists(BasicBlock bb |
|
||||
controlsNullness(e, bb, isNull) and
|
||||
bb = guarded.getAControlFlowNode().getBasicBlock() and
|
||||
exists(ConditionOnExprComparisonConfig c | c.same(e, guarded)) |
|
||||
not guarded.hasSsaQualifier() and not e.hasSsaQualifier()
|
||||
or
|
||||
guarded.getSsaQualifier() = e.getSsaQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate isGuardedByMatching(AccessOrCallExpr guarded, AccessOrCallExpr e, CaseStmt cs, boolean isMatch) {
|
||||
exists(BasicBlock bb |
|
||||
controlsMatching(e, cs, bb, isMatch) and
|
||||
bb = guarded.getAControlFlowNode().getBasicBlock() and
|
||||
exists(ConditionOnExprComparisonConfig c | c.same(e, guarded)) |
|
||||
not guarded.hasSsaQualifier() and not e.hasSsaQualifier()
|
||||
or
|
||||
guarded.getSsaQualifier() = e.getSsaQualifier()
|
||||
)
|
||||
}
|
||||
}
|
||||
import Cached
|
||||
newtype TAbstractValue =
|
||||
TBooleanValue(boolean b) { b = true or b = false }
|
||||
or
|
||||
TNullValue(boolean b) { b = true or b = false }
|
||||
or
|
||||
TMatchValue(CaseStmt cs, boolean b) { b = true or b = false }
|
||||
or
|
||||
TEmptyCollectionValue(boolean b) { b = true or b = false }
|
||||
|
||||
/**
|
||||
* Gets the parent expression of `e` which is `null` iff `e` is null,
|
||||
* Gets the parent expression of `e` which is `null` only if `e` is `null`,
|
||||
* if any. For example, `result = x?.y` and `e = x`, or `result = x + 1`
|
||||
* and `e = x`.
|
||||
*/
|
||||
Expr getNullEquivParent(Expr e) {
|
||||
exists(QualifiableExpr qe |
|
||||
result = qe and
|
||||
result = any(QualifiableExpr qe |
|
||||
qe.getQualifier() = e and
|
||||
qe.isConditional() |
|
||||
qe.(FieldAccess).getTarget().getType() instanceof ValueType or
|
||||
qe.(Call).getTarget().getReturnType() instanceof ValueType
|
||||
qe.isConditional() and
|
||||
(
|
||||
result.(FieldAccess).getTarget().getType() instanceof ValueType
|
||||
or
|
||||
result.(Call).getTarget().getReturnType() instanceof ValueType
|
||||
)
|
||||
)
|
||||
or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
@@ -342,41 +446,6 @@ private module Internal {
|
||||
e.stripCasts() = any(Expr s | s.hasValue() and not s instanceof NullLiteral)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if basic block `bb` only is reached when `cond` evaluates to `b`.
|
||||
* SSA qualified expression `e` is a sub expression of `cond`.
|
||||
*/
|
||||
private predicate controls(Expr cond, AccessOrCallExpr e, BasicBlock bb, boolean b) {
|
||||
exists(ConditionBlock cb | cb.controlsSubCond(bb, _, cond, b)) and
|
||||
cond.getAChildExpr*() = e
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if basic block `bb` only is reached when `e` evaluates to `null`
|
||||
* (`isNull = true`) or when `e` evaluates to non-`null` (`isNull = false`).
|
||||
*/
|
||||
private predicate controlsNullness(Expr e, BasicBlock bb, boolean isNull) {
|
||||
exists(ConditionBlock cb, NullnessSuccessor s |
|
||||
cb.controls(bb, s) |
|
||||
isNull = s.getValue() and
|
||||
e = cb.getLastNode().getElement()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if basic block `bb` only is reached when `e` matches case `cs`
|
||||
* (`isMatch = true`) or when `e` does not match `cs` (`isMatch = false`).
|
||||
*/
|
||||
private predicate controlsMatching(Expr e, CaseStmt cs, BasicBlock bb, boolean isMatch) {
|
||||
exists(ConditionBlock cb, SwitchStmt ss, ControlFlowElement cfe, MatchingSuccessor s |
|
||||
cb.controls(bb, s) |
|
||||
cfe = cb.getLastNode().getElement() and
|
||||
switchMatching(ss, cs, cfe) and
|
||||
e = ss.getCondition() and
|
||||
isMatch = s.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper class for calculating structurally equal access/call expressions.
|
||||
*/
|
||||
@@ -403,13 +472,188 @@ private module Internal {
|
||||
pragma [noinline]
|
||||
private predicate candidateAux(AccessOrCallExpr e, Declaration target, BasicBlock bb) {
|
||||
target = e.getTarget() and
|
||||
(
|
||||
controls(_, e, bb, _)
|
||||
or
|
||||
controlsNullness(e, bb, _)
|
||||
or
|
||||
controlsMatching(e, _, bb, _)
|
||||
)
|
||||
controls(bb, _, e, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if basic block `bb` only is reached when `e` has abstract value `v`.
|
||||
* SSA qualified expression `sub` is a sub expression of `e`.
|
||||
*/
|
||||
private predicate controls(BasicBlock bb, Expr e, AccessOrCallExpr sub, AbstractValue v) {
|
||||
exists(ConditionBlock cb, ConditionalSuccessor s, AbstractValue v0, Expr cond |
|
||||
cb.controls(bb, s) |
|
||||
v0.branchImplies(cb.getLastNode().getElement(), s, cond) and
|
||||
impliesSteps(cond, v0, e, v) and
|
||||
sub = e.getAChildExpr*()
|
||||
)
|
||||
}
|
||||
|
||||
private cached module Cached {
|
||||
cached
|
||||
predicate isGuardedBy(AccessOrCallExpr guarded, Expr e, AccessOrCallExpr sub, AbstractValue v) {
|
||||
exists(BasicBlock bb |
|
||||
controls(bb, e, sub, v) and
|
||||
bb = guarded.getAControlFlowNode().getBasicBlock() and
|
||||
exists(ConditionOnExprComparisonConfig c | c.same(sub, guarded)) |
|
||||
not guarded.hasSsaQualifier() and not sub.hasSsaQualifier()
|
||||
or
|
||||
guarded.getSsaQualifier() = sub.getSsaQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e1` having abstract value `v1` implies that `e2` has abstract
|
||||
* value `v2, using one step of reasoning.
|
||||
*/
|
||||
cached
|
||||
predicate impliesStep(Expr e1, AbstractValue v1, Expr e2, AbstractValue v2) {
|
||||
exists(BinaryOperation bo |
|
||||
bo instanceof BitwiseAndExpr or
|
||||
bo instanceof LogicalAndExpr
|
||||
|
|
||||
bo = e1 and
|
||||
e2 = bo.getAnOperand() and
|
||||
v1 = TBooleanValue(true) and
|
||||
v2 = v1
|
||||
or
|
||||
bo = e2 and
|
||||
e1 = bo.getAnOperand() and
|
||||
v1 = TBooleanValue(false) and
|
||||
v2 = v1
|
||||
)
|
||||
or
|
||||
exists(BinaryOperation bo |
|
||||
bo instanceof BitwiseOrExpr or
|
||||
bo instanceof LogicalOrExpr
|
||||
|
|
||||
bo = e1 and
|
||||
e2 = bo.getAnOperand() and
|
||||
v1 = TBooleanValue(false) and
|
||||
v2 = v1
|
||||
or
|
||||
bo = e2 and
|
||||
e1 = bo.getAnOperand() and
|
||||
v1 = TBooleanValue(true) and
|
||||
v2 = v1
|
||||
)
|
||||
or
|
||||
e1.(LogicalNotExpr).getOperand() = e2 and
|
||||
v2 = TBooleanValue(v1.(BooleanValue).getValue().booleanNot())
|
||||
or
|
||||
e1 = e2.(LogicalNotExpr).getOperand() and
|
||||
v2 = TBooleanValue(v1.(BooleanValue).getValue().booleanNot())
|
||||
or
|
||||
exists(ComparisonTest ct, boolean polarity, BoolLiteral boolLit, boolean b |
|
||||
ct.getAnArgument() = boolLit and
|
||||
b = boolLit.getBoolValue() and
|
||||
v2 = TBooleanValue(v1.(BooleanValue).getValue().booleanXor(polarity).booleanXor(b)) |
|
||||
ct.getComparisonKind().isEquality() and
|
||||
polarity = true and
|
||||
(
|
||||
// e1 === e2 == b, v1 === !(v2 xor b)
|
||||
e1 = ct.getExpr() and
|
||||
e2 = ct.getAnArgument()
|
||||
or
|
||||
// e2 === e1 == b, v1 === !(v2 xor b)
|
||||
e1 = ct.getAnArgument() and
|
||||
e2 = ct.getExpr()
|
||||
)
|
||||
or
|
||||
ct.getComparisonKind().isInequality() and
|
||||
polarity = false and
|
||||
(
|
||||
// e1 === e2 != b, v1 === v2 xor b
|
||||
e1 = ct.getExpr() and
|
||||
e2 = ct.getAnArgument()
|
||||
or
|
||||
// e2 === e1 != true, v1 === v2 xor b
|
||||
e1 = ct.getAnArgument() and
|
||||
e2 = ct.getExpr()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(ConditionalExpr cond, boolean branch, BoolLiteral boolLit, boolean b |
|
||||
b = boolLit.getBoolValue() and
|
||||
(
|
||||
cond.getThen() = boolLit and branch = true
|
||||
or
|
||||
cond.getElse() = boolLit and branch = false
|
||||
)
|
||||
|
|
||||
e1 = cond and
|
||||
v1 = TBooleanValue(b.booleanNot()) and
|
||||
(
|
||||
// e1 === e2 ? b : x, v1 === !b, v2 === false; or
|
||||
// e1 === e2 ? x : b, v1 === !b, v2 === true
|
||||
e2 = cond.getCondition() and
|
||||
v2 = TBooleanValue(branch.booleanNot())
|
||||
or
|
||||
// e1 === x ? e2 : b, v1 === !b, v2 === v1
|
||||
e2 = cond.getThen() and
|
||||
branch = false and
|
||||
v2 = v1
|
||||
or
|
||||
// e1 === x ? b : e2, v1 === !b, v2 === v1
|
||||
e2 = cond.getElse() and
|
||||
branch = true and
|
||||
v2 = v1
|
||||
)
|
||||
or
|
||||
// e2 === e1 ? b : x, v1 === true, v2 === b; or
|
||||
// e2 === e1 ? x : b, v1 === false, v2 === b
|
||||
e1 = cond.getCondition() and
|
||||
e2 = cond and
|
||||
v1 = TBooleanValue(branch) and
|
||||
v2 = TBooleanValue(b)
|
||||
)
|
||||
or
|
||||
exists(boolean isNull |
|
||||
v2 = any(NullValue nv | if nv.isNull() then isNull = true else isNull = false) |
|
||||
e1 = e2.(DereferenceableExpr).getANullCheck(v1, isNull) and
|
||||
(e1 != e2 or v1 != v2)
|
||||
)
|
||||
or
|
||||
e1 instanceof DereferenceableExpr and
|
||||
e1 = getNullEquivParent(e2) and
|
||||
v1 instanceof NullValue and
|
||||
v1 = v2
|
||||
}
|
||||
}
|
||||
import Cached
|
||||
|
||||
/**
|
||||
* Holds if `e1` having some abstract value, `v`, implies that `e2` has the same
|
||||
* abstract value `v`.
|
||||
*/
|
||||
predicate impliesStepIdentity(Expr e1, Expr e2) {
|
||||
exists(PreSsa::Definition def |
|
||||
def.getDefinition().getSource() = e2 |
|
||||
e1 = def.getARead()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e1` having abstract value `v1` implies that `e2` has abstract value
|
||||
* `v2, using zero or more steps of reasoning.
|
||||
*/
|
||||
predicate impliesSteps(Expr e1, AbstractValue v1, Expr e2, AbstractValue v2) {
|
||||
e1.getType() instanceof BoolType and
|
||||
e1 = e2 and
|
||||
v1 = v2 and
|
||||
v1 = TBooleanValue(_)
|
||||
or
|
||||
v1.branchImplies(_, _, e1) and
|
||||
e2 = e1 and
|
||||
v2 = v1
|
||||
or
|
||||
exists(Expr mid, AbstractValue vMid |
|
||||
impliesSteps(e1, v1, mid, vMid) |
|
||||
impliesStep(mid, vMid, e2, v2)
|
||||
or
|
||||
impliesStepIdentity(mid, e2) and
|
||||
v2 = vMid
|
||||
)
|
||||
}
|
||||
}
|
||||
private import Internal
|
||||
|
||||
@@ -46,7 +46,7 @@ module ZipSlip {
|
||||
exists(PropertyAccess pa |
|
||||
this.asExpr() = pa |
|
||||
pa.getTarget().getDeclaringType().hasQualifiedName("System.IO.Compression.ZipArchiveEntry") and
|
||||
pa.getTarget().getName() = "FullName"
|
||||
pa.getTarget().getName() = "FullName"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -150,4 +150,4 @@ module ZipSlip {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Assertions
|
||||
|
||||
select any(FailingAssertion fa)
|
||||
select any(FailingAssertion fa)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:13:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:14:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | true |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:13:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:14:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | true |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:12:13:12:24 | ... > ... | Guards.cs:12:13:12:13 | access to parameter s | true |
|
||||
| Guards.cs:26:31:26:31 | access to parameter s | Guards.cs:24:13:24:21 | ... != ... | Guards.cs:24:13:24:13 | access to parameter s | true |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:13:32:36 | !... | Guards.cs:32:35:32:35 | access to parameter x | true |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:13:32:51 | ... & ... | Guards.cs:32:35:32:35 | access to parameter x | true |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | Guards.cs:32:35:32:35 | access to parameter x | false |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:13:32:51 | ... & ... | Guards.cs:32:42:32:42 | access to parameter y | true |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:40:32:51 | !... | Guards.cs:32:42:32:42 | access to parameter y | true |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:42:32:50 | ... == ... | Guards.cs:32:42:32:42 | access to parameter y | false |
|
||||
| Guards.cs:36:32:36:32 | access to parameter x | Guards.cs:35:13:35:21 | ... == ... | Guards.cs:35:13:35:13 | access to parameter x | false |
|
||||
| Guards.cs:36:36:36:36 | access to parameter y | Guards.cs:35:26:35:34 | ... == ... | Guards.cs:35:26:35:26 | access to parameter y | false |
|
||||
| Guards.cs:39:31:39:31 | access to parameter x | Guards.cs:38:15:38:23 | ... == ... | Guards.cs:38:15:38:15 | access to parameter x | false |
|
||||
| Guards.cs:39:35:39:35 | access to parameter y | Guards.cs:38:28:38:36 | ... == ... | Guards.cs:38:28:38:28 | access to parameter y | false |
|
||||
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:17:41:25 | ... != ... | Guards.cs:41:17:41:17 | access to parameter x | true |
|
||||
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:30:41:38 | ... != ... | Guards.cs:41:30:41:30 | access to parameter y | true |
|
||||
| Guards.cs:48:31:48:40 | access to field Field | Guards.cs:47:13:47:25 | ... != ... | Guards.cs:47:13:47:17 | access to field Field | true |
|
||||
| Guards.cs:55:27:55:27 | access to parameter g | Guards.cs:53:13:53:27 | ... == ... | Guards.cs:53:13:53:13 | access to parameter g | false |
|
||||
| Guards.cs:55:27:55:33 | access to field Field | Guards.cs:53:13:53:27 | ... == ... | Guards.cs:53:13:53:19 | access to field Field | false |
|
||||
| Guards.cs:62:27:62:27 | access to parameter g | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:13 | access to parameter g | false |
|
||||
| Guards.cs:62:27:62:36 | access to property Property | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:22 | access to property Property | false |
|
||||
| Guards.cs:62:27:62:45 | access to property Property | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:31 | access to property Property | false |
|
||||
| Guards.cs:62:27:62:51 | access to field Field | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:37 | access to field Field | false |
|
||||
| Guards.cs:63:27:63:27 | access to parameter g | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:13 | access to parameter g | false |
|
||||
| Guards.cs:63:27:63:36 | access to property Property | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:22 | access to property Property | false |
|
||||
| Guards.cs:70:31:70:31 | access to parameter s | Guards.cs:68:16:68:24 | ... != ... | Guards.cs:68:16:68:16 | access to parameter s | true |
|
||||
| Guards.cs:79:31:79:31 | access to parameter s | Guards.cs:78:13:78:26 | ... == ... | Guards.cs:78:13:78:13 | access to parameter s | true |
|
||||
| Guards.cs:81:31:81:31 | access to parameter s | Guards.cs:80:13:80:25 | ... > ... | Guards.cs:80:13:80:13 | access to parameter s | true |
|
||||
| Guards.cs:83:31:83:31 | access to parameter s | Guards.cs:82:13:82:26 | ... >= ... | Guards.cs:82:13:82:13 | access to parameter s | true |
|
||||
| Guards.cs:85:31:85:31 | access to parameter s | Guards.cs:84:13:84:26 | ... < ... | Guards.cs:84:13:84:13 | access to parameter s | true |
|
||||
| Guards.cs:87:31:87:31 | access to parameter s | Guards.cs:86:13:86:27 | ... <= ... | Guards.cs:86:13:86:13 | access to parameter s | true |
|
||||
| Guards.cs:89:31:89:31 | access to parameter s | Guards.cs:88:13:88:29 | ... != ... | Guards.cs:88:13:88:13 | access to parameter s | true |
|
||||
| Guards.cs:91:31:91:31 | access to parameter s | Guards.cs:88:13:88:29 | ... != ... | Guards.cs:88:13:88:13 | access to parameter s | false |
|
||||
| Guards.cs:93:31:93:31 | access to parameter s | Guards.cs:92:13:92:30 | ... != ... | Guards.cs:92:13:92:13 | access to parameter s | true |
|
||||
| Guards.cs:95:31:95:31 | access to parameter s | Guards.cs:92:13:92:30 | ... != ... | Guards.cs:92:13:92:13 | access to parameter s | false |
|
||||
| Guards.cs:97:31:97:31 | access to parameter s | Guards.cs:96:13:96:19 | ... == ... | Guards.cs:96:13:96:13 | access to parameter s | true |
|
||||
| Guards.cs:99:31:99:31 | access to parameter s | Guards.cs:96:13:96:19 | ... == ... | Guards.cs:96:13:96:13 | access to parameter s | false |
|
||||
| Guards.cs:106:9:106:9 | access to parameter g | Guards.cs:104:13:104:45 | ... == ... | Guards.cs:104:13:104:13 | access to parameter g | false |
|
||||
| Guards.cs:107:27:107:27 | access to parameter g | Guards.cs:104:13:104:45 | ... == ... | Guards.cs:104:13:104:13 | access to parameter g | false |
|
||||
| Guards.cs:108:27:108:27 | access to parameter g | Guards.cs:104:13:104:45 | ... == ... | Guards.cs:104:13:104:13 | access to parameter g | false |
|
||||
| Guards.cs:131:20:131:20 | access to parameter s | Guards.cs:130:13:130:21 | ... is ... | Guards.cs:130:13:130:13 | access to parameter s | true |
|
||||
| Guards.cs:132:16:132:16 | access to parameter s | Guards.cs:130:13:130:21 | ... is ... | Guards.cs:130:13:130:13 | access to parameter s | false |
|
||||
| Guards.cs:138:20:138:20 | access to parameter s | Guards.cs:137:13:137:23 | ... is ... | Guards.cs:137:13:137:13 | access to parameter s | true |
|
||||
| Guards.cs:139:16:139:16 | access to parameter s | Guards.cs:137:13:137:23 | ... is ... | Guards.cs:137:13:137:13 | access to parameter s | false |
|
||||
| Guards.cs:146:16:146:16 | access to parameter o | Guards.cs:144:13:144:25 | ... is ... | Guards.cs:144:13:144:13 | access to parameter o | false |
|
||||
@@ -0,0 +1,6 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
from GuardedExpr ge, Expr e, Access a, boolean b
|
||||
where ge.isGuardedBy(e, a, b)
|
||||
select ge, e, a, b
|
||||
@@ -1,41 +1,122 @@
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:13:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:14:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | true |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:13:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:14:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | true |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:12:13:12:24 | ... > ... | Guards.cs:12:13:12:13 | access to parameter s | true |
|
||||
| Guards.cs:26:31:26:31 | access to parameter s | Guards.cs:24:13:24:13 | access to parameter s | Guards.cs:24:13:24:13 | access to parameter s | non-null |
|
||||
| Guards.cs:26:31:26:31 | access to parameter s | Guards.cs:24:13:24:21 | ... != ... | Guards.cs:24:13:24:13 | access to parameter s | true |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:13:32:36 | !... | Guards.cs:32:35:32:35 | access to parameter x | true |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:13:32:51 | ... & ... | Guards.cs:32:35:32:35 | access to parameter x | true |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | Guards.cs:32:35:32:35 | access to parameter x | false |
|
||||
| Guards.cs:33:31:33:31 | access to parameter x | Guards.cs:32:35:32:35 | access to parameter x | Guards.cs:32:35:32:35 | access to parameter x | non-null |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:13:32:51 | ... & ... | Guards.cs:32:42:32:42 | access to parameter y | true |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:40:32:51 | !... | Guards.cs:32:42:32:42 | access to parameter y | true |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:42:32:42 | access to parameter y | Guards.cs:32:42:32:42 | access to parameter y | non-null |
|
||||
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:42:32:50 | ... == ... | Guards.cs:32:42:32:42 | access to parameter y | false |
|
||||
| Guards.cs:36:32:36:32 | access to parameter x | Guards.cs:35:13:35:13 | access to parameter x | Guards.cs:35:13:35:13 | access to parameter x | non-null |
|
||||
| Guards.cs:36:32:36:32 | access to parameter x | Guards.cs:35:13:35:21 | ... == ... | Guards.cs:35:13:35:13 | access to parameter x | false |
|
||||
| Guards.cs:36:36:36:36 | access to parameter y | Guards.cs:35:26:35:26 | access to parameter y | Guards.cs:35:26:35:26 | access to parameter y | non-null |
|
||||
| Guards.cs:36:36:36:36 | access to parameter y | Guards.cs:35:26:35:34 | ... == ... | Guards.cs:35:26:35:26 | access to parameter y | false |
|
||||
| Guards.cs:39:31:39:31 | access to parameter x | Guards.cs:38:15:38:15 | access to parameter x | Guards.cs:38:15:38:15 | access to parameter x | non-null |
|
||||
| Guards.cs:39:31:39:31 | access to parameter x | Guards.cs:38:15:38:23 | ... == ... | Guards.cs:38:15:38:15 | access to parameter x | false |
|
||||
| Guards.cs:39:35:39:35 | access to parameter y | Guards.cs:38:28:38:28 | access to parameter y | Guards.cs:38:28:38:28 | access to parameter y | non-null |
|
||||
| Guards.cs:39:35:39:35 | access to parameter y | Guards.cs:38:28:38:36 | ... == ... | Guards.cs:38:28:38:28 | access to parameter y | false |
|
||||
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:17:41:17 | access to parameter x | Guards.cs:41:17:41:17 | access to parameter x | non-null |
|
||||
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:17:41:25 | ... != ... | Guards.cs:41:17:41:17 | access to parameter x | true |
|
||||
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:30:41:30 | access to parameter y | Guards.cs:41:30:41:30 | access to parameter y | non-null |
|
||||
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:30:41:38 | ... != ... | Guards.cs:41:30:41:30 | access to parameter y | true |
|
||||
| Guards.cs:48:31:48:40 | access to field Field | Guards.cs:47:13:47:17 | access to field Field | Guards.cs:47:13:47:17 | access to field Field | non-null |
|
||||
| Guards.cs:48:31:48:40 | access to field Field | Guards.cs:47:13:47:25 | ... != ... | Guards.cs:47:13:47:17 | access to field Field | true |
|
||||
| Guards.cs:55:27:55:27 | access to parameter g | Guards.cs:53:13:53:19 | access to field Field | Guards.cs:53:13:53:13 | access to parameter g | non-null |
|
||||
| Guards.cs:55:27:55:27 | access to parameter g | Guards.cs:53:13:53:27 | ... == ... | Guards.cs:53:13:53:13 | access to parameter g | false |
|
||||
| Guards.cs:55:27:55:33 | access to field Field | Guards.cs:53:13:53:19 | access to field Field | Guards.cs:53:13:53:19 | access to field Field | non-null |
|
||||
| Guards.cs:55:27:55:33 | access to field Field | Guards.cs:53:13:53:27 | ... == ... | Guards.cs:53:13:53:19 | access to field Field | false |
|
||||
| Guards.cs:62:27:62:27 | access to parameter g | Guards.cs:60:13:60:37 | access to field Field | Guards.cs:60:13:60:13 | access to parameter g | non-null |
|
||||
| Guards.cs:62:27:62:27 | access to parameter g | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:13 | access to parameter g | false |
|
||||
| Guards.cs:62:27:62:36 | access to property Property | Guards.cs:60:13:60:37 | access to field Field | Guards.cs:60:13:60:22 | access to property Property | non-null |
|
||||
| Guards.cs:62:27:62:36 | access to property Property | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:22 | access to property Property | false |
|
||||
| Guards.cs:62:27:62:45 | access to property Property | Guards.cs:60:13:60:37 | access to field Field | Guards.cs:60:13:60:31 | access to property Property | non-null |
|
||||
| Guards.cs:62:27:62:45 | access to property Property | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:31 | access to property Property | false |
|
||||
| Guards.cs:62:27:62:51 | access to field Field | Guards.cs:60:13:60:37 | access to field Field | Guards.cs:60:13:60:37 | access to field Field | non-null |
|
||||
| Guards.cs:62:27:62:51 | access to field Field | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:37 | access to field Field | false |
|
||||
| Guards.cs:63:27:63:27 | access to parameter g | Guards.cs:60:13:60:37 | access to field Field | Guards.cs:60:13:60:13 | access to parameter g | non-null |
|
||||
| Guards.cs:63:27:63:27 | access to parameter g | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:13 | access to parameter g | false |
|
||||
| Guards.cs:63:27:63:36 | access to property Property | Guards.cs:60:13:60:37 | access to field Field | Guards.cs:60:13:60:22 | access to property Property | non-null |
|
||||
| Guards.cs:63:27:63:36 | access to property Property | Guards.cs:60:13:60:45 | ... == ... | Guards.cs:60:13:60:22 | access to property Property | false |
|
||||
| Guards.cs:70:31:70:31 | access to parameter s | Guards.cs:68:16:68:16 | access to parameter s | Guards.cs:68:16:68:16 | access to parameter s | non-null |
|
||||
| Guards.cs:70:31:70:31 | access to parameter s | Guards.cs:68:16:68:24 | ... != ... | Guards.cs:68:16:68:16 | access to parameter s | true |
|
||||
| Guards.cs:79:31:79:31 | access to parameter s | Guards.cs:78:13:78:13 | access to parameter s | Guards.cs:78:13:78:13 | access to parameter s | non-null |
|
||||
| Guards.cs:79:31:79:31 | access to parameter s | Guards.cs:78:13:78:26 | ... == ... | Guards.cs:78:13:78:13 | access to parameter s | true |
|
||||
| Guards.cs:79:31:79:31 | access to parameter s | Guards.cs:78:15:78:21 | access to property Length | Guards.cs:78:13:78:13 | access to parameter s | non-null |
|
||||
| Guards.cs:81:31:81:31 | access to parameter s | Guards.cs:80:13:80:13 | access to parameter s | Guards.cs:80:13:80:13 | access to parameter s | non-null |
|
||||
| Guards.cs:81:31:81:31 | access to parameter s | Guards.cs:80:13:80:25 | ... > ... | Guards.cs:80:13:80:13 | access to parameter s | true |
|
||||
| Guards.cs:81:31:81:31 | access to parameter s | Guards.cs:80:15:80:21 | access to property Length | Guards.cs:80:13:80:13 | access to parameter s | non-null |
|
||||
| Guards.cs:83:31:83:31 | access to parameter s | Guards.cs:82:13:82:13 | access to parameter s | Guards.cs:82:13:82:13 | access to parameter s | non-null |
|
||||
| Guards.cs:83:31:83:31 | access to parameter s | Guards.cs:82:13:82:26 | ... >= ... | Guards.cs:82:13:82:13 | access to parameter s | true |
|
||||
| Guards.cs:83:31:83:31 | access to parameter s | Guards.cs:82:15:82:21 | access to property Length | Guards.cs:82:13:82:13 | access to parameter s | non-null |
|
||||
| Guards.cs:85:31:85:31 | access to parameter s | Guards.cs:84:13:84:13 | access to parameter s | Guards.cs:84:13:84:13 | access to parameter s | non-null |
|
||||
| Guards.cs:85:31:85:31 | access to parameter s | Guards.cs:84:13:84:26 | ... < ... | Guards.cs:84:13:84:13 | access to parameter s | true |
|
||||
| Guards.cs:85:31:85:31 | access to parameter s | Guards.cs:84:15:84:21 | access to property Length | Guards.cs:84:13:84:13 | access to parameter s | non-null |
|
||||
| Guards.cs:87:31:87:31 | access to parameter s | Guards.cs:86:13:86:13 | access to parameter s | Guards.cs:86:13:86:13 | access to parameter s | non-null |
|
||||
| Guards.cs:87:31:87:31 | access to parameter s | Guards.cs:86:13:86:27 | ... <= ... | Guards.cs:86:13:86:13 | access to parameter s | true |
|
||||
| Guards.cs:87:31:87:31 | access to parameter s | Guards.cs:86:15:86:21 | access to property Length | Guards.cs:86:13:86:13 | access to parameter s | non-null |
|
||||
| Guards.cs:89:31:89:31 | access to parameter s | Guards.cs:88:13:88:13 | access to parameter s | Guards.cs:88:13:88:13 | access to parameter s | non-null |
|
||||
| Guards.cs:89:31:89:31 | access to parameter s | Guards.cs:88:13:88:29 | ... != ... | Guards.cs:88:13:88:13 | access to parameter s | true |
|
||||
| Guards.cs:89:31:89:31 | access to parameter s | Guards.cs:88:15:88:21 | access to property Length | Guards.cs:88:13:88:13 | access to parameter s | non-null |
|
||||
| Guards.cs:91:31:91:31 | access to parameter s | Guards.cs:88:13:88:13 | access to parameter s | Guards.cs:88:13:88:13 | access to parameter s | null |
|
||||
| Guards.cs:91:31:91:31 | access to parameter s | Guards.cs:88:13:88:29 | ... != ... | Guards.cs:88:13:88:13 | access to parameter s | false |
|
||||
| Guards.cs:91:31:91:31 | access to parameter s | Guards.cs:88:15:88:21 | access to property Length | Guards.cs:88:13:88:13 | access to parameter s | null |
|
||||
| Guards.cs:93:31:93:31 | access to parameter s | Guards.cs:92:13:92:30 | ... != ... | Guards.cs:92:13:92:13 | access to parameter s | true |
|
||||
| Guards.cs:95:31:95:31 | access to parameter s | Guards.cs:92:13:92:13 | access to parameter s | Guards.cs:92:13:92:13 | access to parameter s | non-null |
|
||||
| Guards.cs:95:31:95:31 | access to parameter s | Guards.cs:92:13:92:25 | ... - ... | Guards.cs:92:13:92:13 | access to parameter s | non-null |
|
||||
| Guards.cs:95:31:95:31 | access to parameter s | Guards.cs:92:13:92:30 | ... != ... | Guards.cs:92:13:92:13 | access to parameter s | false |
|
||||
| Guards.cs:95:31:95:31 | access to parameter s | Guards.cs:92:15:92:21 | access to property Length | Guards.cs:92:13:92:13 | access to parameter s | non-null |
|
||||
| Guards.cs:97:31:97:31 | access to parameter s | Guards.cs:96:13:96:13 | access to parameter s | Guards.cs:96:13:96:13 | access to parameter s | non-null |
|
||||
| Guards.cs:97:31:97:31 | access to parameter s | Guards.cs:96:13:96:19 | ... == ... | Guards.cs:96:13:96:13 | access to parameter s | true |
|
||||
| Guards.cs:99:31:99:31 | access to parameter s | Guards.cs:96:13:96:19 | ... == ... | Guards.cs:96:13:96:13 | access to parameter s | false |
|
||||
| Guards.cs:106:9:106:9 | access to parameter g | Guards.cs:104:13:104:37 | access to field Field | Guards.cs:104:13:104:13 | access to parameter g | non-null |
|
||||
| Guards.cs:106:9:106:9 | access to parameter g | Guards.cs:104:13:104:45 | ... == ... | Guards.cs:104:13:104:13 | access to parameter g | false |
|
||||
| Guards.cs:107:27:107:27 | access to parameter g | Guards.cs:104:13:104:37 | access to field Field | Guards.cs:104:13:104:13 | access to parameter g | non-null |
|
||||
| Guards.cs:107:27:107:27 | access to parameter g | Guards.cs:104:13:104:45 | ... == ... | Guards.cs:104:13:104:13 | access to parameter g | false |
|
||||
| Guards.cs:108:27:108:27 | access to parameter g | Guards.cs:104:13:104:37 | access to field Field | Guards.cs:104:13:104:13 | access to parameter g | non-null |
|
||||
| Guards.cs:108:27:108:27 | access to parameter g | Guards.cs:104:13:104:45 | ... == ... | Guards.cs:104:13:104:13 | access to parameter g | false |
|
||||
| Guards.cs:114:14:114:14 | access to parameter g | Guards.cs:113:21:113:45 | access to field Field | Guards.cs:113:21:113:21 | access to parameter g | null |
|
||||
| Guards.cs:114:14:114:23 | access to property Property | Guards.cs:113:21:113:45 | access to field Field | Guards.cs:113:21:113:30 | access to property Property | null |
|
||||
| Guards.cs:114:14:114:32 | access to property Property | Guards.cs:113:21:113:45 | access to field Field | Guards.cs:113:21:113:39 | access to property Property | null |
|
||||
| Guards.cs:114:14:114:38 | access to field Field | Guards.cs:113:21:113:45 | access to field Field | Guards.cs:113:21:113:45 | access to field Field | null |
|
||||
| Guards.cs:116:27:116:27 | access to parameter g | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:17 | access to parameter g | non-null |
|
||||
| Guards.cs:116:27:116:36 | access to property Property | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:26 | access to property Property | non-null |
|
||||
| Guards.cs:116:27:116:45 | access to property Property | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:35 | access to property Property | non-null |
|
||||
| Guards.cs:116:27:116:51 | access to field Field | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:41 | access to field Field | non-null |
|
||||
| Guards.cs:117:9:117:9 | access to parameter g | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:17 | access to parameter g | non-null |
|
||||
| Guards.cs:118:27:118:27 | access to parameter g | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:17 | access to parameter g | non-null |
|
||||
| Guards.cs:119:27:119:27 | access to parameter g | Guards.cs:115:17:115:41 | access to field Field | Guards.cs:115:17:115:17 | access to parameter g | non-null |
|
||||
| Guards.cs:125:29:125:30 | access to parameter s1 | Guards.cs:125:18:125:19 | access to parameter s1 | Guards.cs:125:18:125:19 | access to parameter s1 | non-null |
|
||||
| Guards.cs:131:20:131:20 | access to parameter s | Guards.cs:130:13:130:13 | access to parameter s | Guards.cs:130:13:130:13 | access to parameter s | null |
|
||||
| Guards.cs:131:20:131:20 | access to parameter s | Guards.cs:130:13:130:21 | ... is ... | Guards.cs:130:13:130:13 | access to parameter s | true |
|
||||
| Guards.cs:132:16:132:16 | access to parameter s | Guards.cs:130:13:130:13 | access to parameter s | Guards.cs:130:13:130:13 | access to parameter s | non-null |
|
||||
| Guards.cs:132:16:132:16 | access to parameter s | Guards.cs:130:13:130:21 | ... is ... | Guards.cs:130:13:130:13 | access to parameter s | false |
|
||||
| Guards.cs:138:20:138:20 | access to parameter s | Guards.cs:137:13:137:13 | access to parameter s | Guards.cs:137:13:137:13 | access to parameter s | non-null |
|
||||
| Guards.cs:138:20:138:20 | access to parameter s | Guards.cs:137:13:137:23 | ... is ... | Guards.cs:137:13:137:13 | access to parameter s | true |
|
||||
| Guards.cs:139:16:139:16 | access to parameter s | Guards.cs:137:13:137:23 | ... is ... | Guards.cs:137:13:137:13 | access to parameter s | false |
|
||||
| Guards.cs:146:16:146:16 | access to parameter o | Guards.cs:144:13:144:25 | ... is ... | Guards.cs:144:13:144:13 | access to parameter o | false |
|
||||
| Guards.cs:154:24:154:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | match case Action<Object>: |
|
||||
| Guards.cs:154:24:154:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
| Guards.cs:158:24:158:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | match case ...: |
|
||||
| Guards.cs:158:24:158:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case Action<Object>: |
|
||||
| Guards.cs:158:24:158:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case Action<String> a: |
|
||||
| Guards.cs:158:24:158:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
| Guards.cs:160:24:160:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | match case ...: |
|
||||
| Guards.cs:160:24:160:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case ...: |
|
||||
| Guards.cs:160:24:160:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case Action<Object>: |
|
||||
| Guards.cs:160:24:160:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case Action<String> a: |
|
||||
| Guards.cs:160:24:160:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | null |
|
||||
| Guards.cs:162:24:162:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case ...: |
|
||||
| Guards.cs:162:24:162:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case ...: |
|
||||
| Guards.cs:162:24:162:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case Action<Object>: |
|
||||
| Guards.cs:162:24:162:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-match case Action<String> a: |
|
||||
| Guards.cs:162:24:162:24 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
from GuardedExpr ge, Expr e, Access a, boolean b
|
||||
where ge.isGuardedBy(e, a, b)
|
||||
select ge, e, a, b
|
||||
from GuardedExpr ge, Expr sub, AbstractValue v
|
||||
select ge, ge.getAGuard(sub, v), sub, v
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
impliesStep
|
||||
| Guards.cs:10:13:10:25 | !... | false | Guards.cs:10:14:10:25 | !... | true |
|
||||
| Guards.cs:10:13:10:25 | !... | true | Guards.cs:10:14:10:25 | !... | false |
|
||||
| Guards.cs:10:14:10:25 | !... | false | Guards.cs:10:13:10:25 | !... | true |
|
||||
| Guards.cs:10:14:10:25 | !... | false | Guards.cs:10:16:10:24 | ... == ... | true |
|
||||
| Guards.cs:10:14:10:25 | !... | true | Guards.cs:10:13:10:25 | !... | false |
|
||||
| Guards.cs:10:14:10:25 | !... | true | Guards.cs:10:16:10:24 | ... == ... | false |
|
||||
| Guards.cs:10:16:10:24 | ... == ... | false | Guards.cs:10:14:10:25 | !... | true |
|
||||
| Guards.cs:10:16:10:24 | ... == ... | false | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
| Guards.cs:10:16:10:24 | ... == ... | true | Guards.cs:10:14:10:25 | !... | false |
|
||||
| Guards.cs:10:16:10:24 | ... == ... | true | Guards.cs:10:16:10:16 | access to parameter s | null |
|
||||
| Guards.cs:24:13:24:21 | ... != ... | false | Guards.cs:24:13:24:13 | access to parameter s | null |
|
||||
| Guards.cs:24:13:24:21 | ... != ... | true | Guards.cs:24:13:24:13 | access to parameter s | non-null |
|
||||
| Guards.cs:32:13:32:36 | !... | false | Guards.cs:32:13:32:51 | ... & ... | false |
|
||||
| Guards.cs:32:13:32:36 | !... | false | Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | true |
|
||||
| Guards.cs:32:13:32:36 | !... | true | Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | false |
|
||||
| Guards.cs:32:13:32:51 | ... & ... | true | Guards.cs:32:13:32:36 | !... | true |
|
||||
| Guards.cs:32:13:32:51 | ... & ... | true | Guards.cs:32:40:32:51 | !... | true |
|
||||
| Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | false | Guards.cs:32:13:32:36 | !... | true |
|
||||
| Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | false | Guards.cs:32:35:32:35 | access to parameter x | non-null |
|
||||
| Guards.cs:32:14:32:36 | call to method IsNullOrEmpty | true | Guards.cs:32:13:32:36 | !... | false |
|
||||
| Guards.cs:32:40:32:51 | !... | false | Guards.cs:32:13:32:51 | ... & ... | false |
|
||||
| Guards.cs:32:40:32:51 | !... | false | Guards.cs:32:42:32:50 | ... == ... | true |
|
||||
| Guards.cs:32:40:32:51 | !... | true | Guards.cs:32:42:32:50 | ... == ... | false |
|
||||
| Guards.cs:32:42:32:50 | ... == ... | false | Guards.cs:32:40:32:51 | !... | true |
|
||||
| Guards.cs:32:42:32:50 | ... == ... | false | Guards.cs:32:42:32:42 | access to parameter y | non-null |
|
||||
| Guards.cs:32:42:32:50 | ... == ... | true | Guards.cs:32:40:32:51 | !... | false |
|
||||
| Guards.cs:32:42:32:50 | ... == ... | true | Guards.cs:32:42:32:42 | access to parameter y | null |
|
||||
| Guards.cs:35:13:35:21 | ... == ... | false | Guards.cs:35:13:35:13 | access to parameter x | non-null |
|
||||
| Guards.cs:35:13:35:21 | ... == ... | true | Guards.cs:35:13:35:13 | access to parameter x | null |
|
||||
| Guards.cs:35:13:35:21 | ... == ... | true | Guards.cs:35:13:35:34 | ... \|\| ... | true |
|
||||
| Guards.cs:35:13:35:34 | ... \|\| ... | false | Guards.cs:35:13:35:21 | ... == ... | false |
|
||||
| Guards.cs:35:13:35:34 | ... \|\| ... | false | Guards.cs:35:26:35:34 | ... == ... | false |
|
||||
| Guards.cs:35:26:35:34 | ... == ... | false | Guards.cs:35:26:35:26 | access to parameter y | non-null |
|
||||
| Guards.cs:35:26:35:34 | ... == ... | true | Guards.cs:35:13:35:34 | ... \|\| ... | true |
|
||||
| Guards.cs:35:26:35:34 | ... == ... | true | Guards.cs:35:26:35:26 | access to parameter y | null |
|
||||
| Guards.cs:38:13:38:37 | !... | false | Guards.cs:38:15:38:36 | ... \|\| ... | true |
|
||||
| Guards.cs:38:13:38:37 | !... | true | Guards.cs:38:15:38:36 | ... \|\| ... | false |
|
||||
| Guards.cs:38:15:38:23 | ... == ... | false | Guards.cs:38:15:38:15 | access to parameter x | non-null |
|
||||
| Guards.cs:38:15:38:23 | ... == ... | true | Guards.cs:38:15:38:15 | access to parameter x | null |
|
||||
| Guards.cs:38:15:38:23 | ... == ... | true | Guards.cs:38:15:38:36 | ... \|\| ... | true |
|
||||
| Guards.cs:38:15:38:36 | ... \|\| ... | false | Guards.cs:38:13:38:37 | !... | true |
|
||||
| Guards.cs:38:15:38:36 | ... \|\| ... | false | Guards.cs:38:15:38:23 | ... == ... | false |
|
||||
| Guards.cs:38:15:38:36 | ... \|\| ... | false | Guards.cs:38:28:38:36 | ... == ... | false |
|
||||
| Guards.cs:38:15:38:36 | ... \|\| ... | true | Guards.cs:38:13:38:37 | !... | false |
|
||||
| Guards.cs:38:28:38:36 | ... == ... | false | Guards.cs:38:28:38:28 | access to parameter y | non-null |
|
||||
| Guards.cs:38:28:38:36 | ... == ... | true | Guards.cs:38:15:38:36 | ... \|\| ... | true |
|
||||
| Guards.cs:38:28:38:36 | ... == ... | true | Guards.cs:38:28:38:28 | access to parameter y | null |
|
||||
| Guards.cs:41:13:41:39 | !... | false | Guards.cs:41:14:41:39 | !... | true |
|
||||
| Guards.cs:41:13:41:39 | !... | true | Guards.cs:41:14:41:39 | !... | false |
|
||||
| Guards.cs:41:14:41:39 | !... | false | Guards.cs:41:13:41:39 | !... | true |
|
||||
| Guards.cs:41:14:41:39 | !... | false | Guards.cs:41:15:41:39 | !... | true |
|
||||
| Guards.cs:41:14:41:39 | !... | true | Guards.cs:41:13:41:39 | !... | false |
|
||||
| Guards.cs:41:14:41:39 | !... | true | Guards.cs:41:15:41:39 | !... | false |
|
||||
| Guards.cs:41:15:41:39 | !... | false | Guards.cs:41:14:41:39 | !... | true |
|
||||
| Guards.cs:41:15:41:39 | !... | false | Guards.cs:41:17:41:38 | ... && ... | true |
|
||||
| Guards.cs:41:15:41:39 | !... | true | Guards.cs:41:14:41:39 | !... | false |
|
||||
| Guards.cs:41:15:41:39 | !... | true | Guards.cs:41:17:41:38 | ... && ... | false |
|
||||
| Guards.cs:41:17:41:25 | ... != ... | false | Guards.cs:41:17:41:17 | access to parameter x | null |
|
||||
| Guards.cs:41:17:41:25 | ... != ... | false | Guards.cs:41:17:41:38 | ... && ... | false |
|
||||
| Guards.cs:41:17:41:25 | ... != ... | true | Guards.cs:41:17:41:17 | access to parameter x | non-null |
|
||||
| Guards.cs:41:17:41:38 | ... && ... | false | Guards.cs:41:15:41:39 | !... | true |
|
||||
| Guards.cs:41:17:41:38 | ... && ... | true | Guards.cs:41:15:41:39 | !... | false |
|
||||
| Guards.cs:41:17:41:38 | ... && ... | true | Guards.cs:41:17:41:25 | ... != ... | true |
|
||||
| Guards.cs:41:17:41:38 | ... && ... | true | Guards.cs:41:30:41:38 | ... != ... | true |
|
||||
| Guards.cs:41:30:41:38 | ... != ... | false | Guards.cs:41:17:41:38 | ... && ... | false |
|
||||
| Guards.cs:41:30:41:38 | ... != ... | false | Guards.cs:41:30:41:30 | access to parameter y | null |
|
||||
| Guards.cs:41:30:41:38 | ... != ... | true | Guards.cs:41:30:41:30 | access to parameter y | non-null |
|
||||
| Guards.cs:44:13:44:25 | ... != ... | false | Guards.cs:44:13:44:17 | access to field Field | null |
|
||||
| Guards.cs:44:13:44:25 | ... != ... | true | Guards.cs:44:13:44:17 | access to field Field | non-null |
|
||||
| Guards.cs:47:13:47:25 | ... != ... | false | Guards.cs:47:13:47:17 | access to field Field | null |
|
||||
| Guards.cs:47:13:47:25 | ... != ... | true | Guards.cs:47:13:47:17 | access to field Field | non-null |
|
||||
| Guards.cs:53:13:53:27 | ... == ... | false | Guards.cs:53:13:53:19 | access to field Field | non-null |
|
||||
| Guards.cs:53:13:53:27 | ... == ... | true | Guards.cs:53:13:53:19 | access to field Field | null |
|
||||
| Guards.cs:60:13:60:45 | ... == ... | false | Guards.cs:60:13:60:37 | access to field Field | non-null |
|
||||
| Guards.cs:60:13:60:45 | ... == ... | true | Guards.cs:60:13:60:37 | access to field Field | null |
|
||||
| Guards.cs:68:16:68:24 | ... != ... | false | Guards.cs:68:16:68:16 | access to parameter s | null |
|
||||
| Guards.cs:68:16:68:24 | ... != ... | true | Guards.cs:68:16:68:16 | access to parameter s | non-null |
|
||||
| Guards.cs:78:13:78:26 | ... == ... | true | Guards.cs:78:15:78:21 | access to property Length | non-null |
|
||||
| Guards.cs:78:15:78:21 | access to property Length | non-null | Guards.cs:78:13:78:13 | access to parameter s | non-null |
|
||||
| Guards.cs:78:15:78:21 | access to property Length | null | Guards.cs:78:13:78:13 | access to parameter s | null |
|
||||
| Guards.cs:80:13:80:25 | ... > ... | true | Guards.cs:80:15:80:21 | access to property Length | non-null |
|
||||
| Guards.cs:80:15:80:21 | access to property Length | non-null | Guards.cs:80:13:80:13 | access to parameter s | non-null |
|
||||
| Guards.cs:80:15:80:21 | access to property Length | null | Guards.cs:80:13:80:13 | access to parameter s | null |
|
||||
| Guards.cs:82:13:82:26 | ... >= ... | true | Guards.cs:82:15:82:21 | access to property Length | non-null |
|
||||
| Guards.cs:82:15:82:21 | access to property Length | non-null | Guards.cs:82:13:82:13 | access to parameter s | non-null |
|
||||
| Guards.cs:82:15:82:21 | access to property Length | null | Guards.cs:82:13:82:13 | access to parameter s | null |
|
||||
| Guards.cs:84:13:84:26 | ... < ... | true | Guards.cs:84:15:84:21 | access to property Length | non-null |
|
||||
| Guards.cs:84:15:84:21 | access to property Length | non-null | Guards.cs:84:13:84:13 | access to parameter s | non-null |
|
||||
| Guards.cs:84:15:84:21 | access to property Length | null | Guards.cs:84:13:84:13 | access to parameter s | null |
|
||||
| Guards.cs:86:13:86:27 | ... <= ... | true | Guards.cs:86:15:86:21 | access to property Length | non-null |
|
||||
| Guards.cs:86:15:86:21 | access to property Length | non-null | Guards.cs:86:13:86:13 | access to parameter s | non-null |
|
||||
| Guards.cs:86:15:86:21 | access to property Length | null | Guards.cs:86:13:86:13 | access to parameter s | null |
|
||||
| Guards.cs:88:13:88:29 | ... != ... | false | Guards.cs:88:15:88:21 | access to property Length | null |
|
||||
| Guards.cs:88:13:88:29 | ... != ... | true | Guards.cs:88:15:88:21 | access to property Length | non-null |
|
||||
| Guards.cs:88:15:88:21 | access to property Length | non-null | Guards.cs:88:13:88:13 | access to parameter s | non-null |
|
||||
| Guards.cs:88:15:88:21 | access to property Length | null | Guards.cs:88:13:88:13 | access to parameter s | null |
|
||||
| Guards.cs:92:13:92:25 | ... - ... | non-null | Guards.cs:92:15:92:21 | access to property Length | non-null |
|
||||
| Guards.cs:92:13:92:25 | ... - ... | null | Guards.cs:92:15:92:21 | access to property Length | null |
|
||||
| Guards.cs:92:13:92:30 | ... != ... | false | Guards.cs:92:13:92:25 | ... - ... | non-null |
|
||||
| Guards.cs:92:15:92:21 | access to property Length | non-null | Guards.cs:92:13:92:13 | access to parameter s | non-null |
|
||||
| Guards.cs:92:15:92:21 | access to property Length | null | Guards.cs:92:13:92:13 | access to parameter s | null |
|
||||
| Guards.cs:96:13:96:19 | ... == ... | true | Guards.cs:96:13:96:13 | access to parameter s | non-null |
|
||||
| Guards.cs:104:13:104:45 | ... == ... | false | Guards.cs:104:13:104:37 | access to field Field | non-null |
|
||||
| Guards.cs:104:13:104:45 | ... == ... | true | Guards.cs:104:13:104:37 | access to field Field | null |
|
||||
| Guards.cs:125:21:125:31 | call to method Equals | non-null | Guards.cs:125:18:125:19 | access to parameter s1 | non-null |
|
||||
| Guards.cs:125:21:125:31 | call to method Equals | null | Guards.cs:125:18:125:19 | access to parameter s1 | null |
|
||||
| Guards.cs:130:13:130:21 | ... is ... | false | Guards.cs:130:13:130:13 | access to parameter s | non-null |
|
||||
| Guards.cs:130:13:130:21 | ... is ... | true | Guards.cs:130:13:130:13 | access to parameter s | null |
|
||||
| Guards.cs:137:13:137:23 | ... is ... | true | Guards.cs:137:13:137:13 | access to parameter s | non-null |
|
||||
| Guards.cs:144:13:144:25 | ... is ... | true | Guards.cs:144:13:144:13 | access to parameter o | non-null |
|
||||
| Guards.cs:151:17:151:17 | access to parameter o | match case ...: | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
| Guards.cs:151:17:151:17 | access to parameter o | match case ...: | Guards.cs:151:17:151:17 | access to parameter o | null |
|
||||
| Guards.cs:151:17:151:17 | access to parameter o | match case Action<Object>: | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
| Guards.cs:151:17:151:17 | access to parameter o | match case Action<String> a: | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
| Guards.cs:151:17:151:17 | access to parameter o | non-match case ...: | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
impliesStepIdentity
|
||||
| Guards.cs:72:31:72:31 | access to parameter s | Guards.cs:71:17:71:20 | null |
|
||||
| Guards.cs:145:20:145:20 | access to local variable s | Guards.cs:144:13:144:13 | access to parameter o |
|
||||
| Guards.cs:156:24:156:24 | access to local variable a | Guards.cs:151:17:151:17 | access to parameter o |
|
||||
@@ -0,0 +1,10 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
query predicate impliesStep(Expr e1, AbstractValue v1, Expr e2, AbstractValue v2) {
|
||||
Internal::impliesStep(e1, v1, e2, v2)
|
||||
}
|
||||
|
||||
query predicate impliesStepIdentity(Expr e1, Expr e2) {
|
||||
Internal::impliesStepIdentity(e1, e2)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
from MatchingGuardedExpr mge, Expr e, CaseStmt cs, boolean isMatch
|
||||
where mge.isGuardedBy(e, cs, isMatch)
|
||||
select mge, e, cs, isMatch
|
||||
from GuardedExpr ge, Expr e, AbstractValues::MatchValue v, boolean match
|
||||
where e = ge.getAGuard(e, v)
|
||||
and if v.isMatch() then match = true else match = false
|
||||
select ge, e, v.getCaseStmt(), match
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
| Guards.cs:114:14:114:38 | access to field Field | Guards.cs:113:21:113:45 | access to field Field | true |
|
||||
| Guards.cs:116:27:116:51 | access to field Field | Guards.cs:115:17:115:41 | access to field Field | false |
|
||||
| Guards.cs:125:29:125:30 | access to parameter s1 | Guards.cs:125:18:125:19 | access to parameter s1 | false |
|
||||
@@ -1,6 +0,0 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
from NullnessGuardedExpr nge, Expr e, boolean isNull
|
||||
where nge.isGuardedBy(e, isNull)
|
||||
select nge, e, isNull
|
||||
@@ -9,11 +9,11 @@ class LocalTest
|
||||
{
|
||||
lock (a) lock (b) lock(c) { }
|
||||
}
|
||||
|
||||
|
||||
void G()
|
||||
{
|
||||
lock (a) lock (c) lock(b) { }
|
||||
}
|
||||
}
|
||||
|
||||
void H()
|
||||
{
|
||||
@@ -30,18 +30,18 @@ class GlobalTest
|
||||
{
|
||||
lock (a) G();
|
||||
}
|
||||
|
||||
|
||||
void G()
|
||||
{
|
||||
lock (b) H();
|
||||
lock (c) I();
|
||||
}
|
||||
|
||||
|
||||
void H()
|
||||
{
|
||||
lock (c) { }
|
||||
}
|
||||
|
||||
|
||||
void I()
|
||||
{
|
||||
lock (b) { }
|
||||
@@ -52,12 +52,12 @@ class LambdaTest
|
||||
{
|
||||
// BAD: a is flagged.
|
||||
static Object a, b;
|
||||
|
||||
|
||||
void F()
|
||||
{
|
||||
Action lock_a = () => { lock(a) { } };
|
||||
Action lock_b = () => { lock(b) { } };
|
||||
|
||||
|
||||
lock(a) lock_b();
|
||||
lock(b) lock_a();
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@ class Bad
|
||||
string destFileName = Path.Combine(destDirectory, entry.FullName);
|
||||
entry.ExtractToFile(destFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user