Skip to content

Commit 7c52170

Browse files
authored
Merge pull request #76 from hvitved/csharp/cfg/generic-splitting
C#: Generic control flow graph splitting
2 parents 61bd003 + bae3265 commit 7c52170

19 files changed

+3623
-2204
lines changed

change-notes/1.18/analysis-csharp.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
99
## General improvements
1010

11-
> Changes that affect alerts in many files or from many queries
12-
> For example, changes to file classification
11+
* Control flow analysis has been improved for `catch` clauses with filters.
1312

1413
## New queries
1514

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,8 @@ class TryStmt extends Stmt, @try_stmt {
971971
* general `catch` clause (`GeneralCatchClause`).
972972
*/
973973
class CatchClause extends Stmt, @catch {
974+
/** Gets the `try` statement that this `catch` clause belongs to. */
975+
TryStmt getTryStmt() { result.getACatchClause() = this }
974976

975977
/** Gets the block of this `catch` clause. */
976978
BlockStmt getBlock() { result.getParent() = this }
@@ -1007,6 +1009,15 @@ class CatchClause extends Stmt, @catch {
10071009

10081010
/** Holds if this `catch` clause has a filter. */
10091011
predicate hasFilterClause() { exists(getFilterClause()) }
1012+
1013+
/** Holds if this is the last `catch` clause in the `try` statement that it belongs to. */
1014+
predicate isLast() {
1015+
exists(TryStmt ts, int last |
1016+
ts = this.getTryStmt() and
1017+
last = max(int i | exists(ts.getCatchClause(i))) and
1018+
this = ts.getCatchClause(last)
1019+
)
1020+
}
10101021
}
10111022

10121023
/**

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class Completion extends TCompletion {
101101
or
102102
not isNullnessConstant(cfe, _) and
103103
this = TNullnessCompletion(_)
104-
else if mustHaveMatchingCompletion(_, cfe) then
104+
else if mustHaveMatchingCompletion(cfe) then
105105
exists(boolean value |
106106
isMatchingConstant(cfe, value) |
107107
this = TMatchingCompletion(value)
@@ -123,11 +123,6 @@ class Completion extends TCompletion {
123123
this instanceof NormalCompletion or
124124
this instanceof ContinueCompletion
125125
}
126-
127-
/** Holds if this completion is a valid completion for exiting a callable. */
128-
predicate isValidCallableExitCompletion() {
129-
not this instanceof GotoCompletion
130-
}
131126
}
132127

133128
/** Holds if expression `e` has the Boolean constant value `value`. */
@@ -319,6 +314,11 @@ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent)
319314
isBooleanCompletionForParent = false
320315
)
321316
or
317+
exists(SpecificCatchClause scc |
318+
scc.getFilterClause() = e |
319+
isBooleanCompletionForParent = false
320+
)
321+
or
322322
exists(LogicalNotExpr lne |
323323
lne.getAnOperand() = e |
324324
inBooleanContext(lne, _) and
@@ -401,14 +401,20 @@ private predicate inNullnessContext(Expr e, boolean isNullnessCompletionForParen
401401
)
402402
}
403403

404+
private predicate mustHaveMatchingCompletion(SwitchStmt ss, ControlFlowElement cfe) {
405+
cfe = ss.getAConstCase().getExpr()
406+
or
407+
cfe = ss.getATypeCase().getTypeAccess() // use type access to represent the type test
408+
}
409+
404410
/**
405-
* Holds if a normal completion of `e` must be a matching completion. Thats is,
406-
* whether `e` determines a match in a `switch` statement.
411+
* Holds if a normal completion of `cfe` must be a matching completion. Thats is,
412+
* whether `cfe` determines a match in a `switch` statement or `catch` clause.
407413
*/
408-
private predicate mustHaveMatchingCompletion(SwitchStmt ss, Expr e) {
409-
e = ss.getAConstCase().getExpr()
414+
private predicate mustHaveMatchingCompletion(ControlFlowElement cfe) {
415+
mustHaveMatchingCompletion(_, cfe)
410416
or
411-
e = ss.getATypeCase().getTypeAccess() // use type access to represent the type test
417+
cfe instanceof SpecificCatchClause
412418
}
413419

414420
/**

0 commit comments

Comments
 (0)