Skip to content

Commit ab9aa7d

Browse files
committed
C#: Teach guards library about conditional assignments
For example, in ``` void M(object x) { var y = x != null ? "" : null; if (y != null) x.ToString(); } ``` the guard `y != null` implies that the guard `x != null` must be true.
1 parent 80144a0 commit ab9aa7d

File tree

12 files changed

+662
-23
lines changed

12 files changed

+662
-23
lines changed

csharp/ql/src/semmle/code/csharp/Stmt.qll

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,12 +966,17 @@ class TryStmt extends Stmt, @try_stmt {
966966
exists(ControlFlowElement mid |
967967
mid = getATriedElement() and
968968
not mid instanceof TryStmt and
969-
result = mid.getAChild() and
970-
mid.getEnclosingCallable() = result.getEnclosingCallable()
969+
result = getAChild(mid, mid.getEnclosingCallable())
971970
)
972971
}
973972
}
974973

974+
pragma[noinline]
975+
private ControlFlowElement getAChild(ControlFlowElement cfe, Callable c) {
976+
result = cfe.getAChild() and
977+
c = result.getEnclosingCallable()
978+
}
979+
975980
/**
976981
* A `catch` clause within a `try` statement.
977982
*

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,7 +2497,11 @@ module ControlFlow {
24972497
class PreBasicBlock extends ControlFlowElement {
24982498
PreBasicBlock() { startsBB(this) }
24992499

2500-
PreBasicBlock getASuccessor() { result = succ(this.getLastElement(), _) }
2500+
PreBasicBlock getASuccessorByType(SuccessorType t) {
2501+
result = succ(this.getLastElement(), any(Completion c | t.matchesCompletion(c)))
2502+
}
2503+
2504+
PreBasicBlock getASuccessor() { result = this.getASuccessorByType(_) }
25012505

25022506
PreBasicBlock getAPredecessor() {
25032507
result.getASuccessor() = this
@@ -3099,6 +3103,12 @@ module ControlFlow {
30993103
}
31003104
}
31013105

3106+
pragma[noinline]
3107+
private ControlFlowElement getAChild(ControlFlowElement cfe, Callable c) {
3108+
result = cfe.getAChild() and
3109+
c = result.getEnclosingCallable()
3110+
}
3111+
31023112
/**
31033113
* Gets a descendant that belongs to the `finally` block of try statement
31043114
* `try`.
@@ -3108,8 +3118,7 @@ module ControlFlow {
31083118
or
31093119
exists(ControlFlowElement mid |
31103120
mid = getAFinallyDescendant(try) and
3111-
result = mid.getAChild() and
3112-
mid.getEnclosingCallable() = result.getEnclosingCallable() and
3121+
result = getAChild(mid, mid.getEnclosingCallable()) and
31133122
not exists(TryStmt nestedTry |
31143123
result = nestedTry.getFinally() and
31153124
nestedTry != try

0 commit comments

Comments
 (0)