Merge pull request #355 from hvitved/csharp/guards-logic

Approved by calumgrant
This commit is contained in:
semmle-qlci
2018-11-06 19:06:30 +00:00
committed by GitHub
23 changed files with 828 additions and 303 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -9,4 +9,4 @@ class Bad
string destFileName = Path.Combine(destDirectory, entry.FullName);
entry.ExtractToFile(destFileName);
}
}
}

View File

@@ -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() +

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
}
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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 {
)
}
}
}
}

View File

@@ -1,4 +1,4 @@
import csharp
import semmle.code.csharp.commons.Assertions
select any(FailingAssertion fa)
select any(FailingAssertion fa)

View File

@@ -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 |

View File

@@ -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

View File

@@ -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 |

View File

@@ -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

View File

@@ -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 |

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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 |

View File

@@ -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

View File

@@ -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();
}

View File

@@ -9,4 +9,4 @@ class Bad
string destFileName = Path.Combine(destDirectory, entry.FullName);
entry.ExtractToFile(destFileName);
}
}
}