Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f91e460

Browse files
committed
C#: Introduce inherited CFG completions
When completions are inherited by elements inside `finally` blocks, we previously threw away the underlying completion. For example, in ``` try { if (b) throw new Exception(); } finally { if (b) ... } ``` the completions for `b` inside the `finally` block are `true` and `throw(Exception)`, where the latter is inherited from the `try` block, with an underlying `false` completion. Throwing away the `false` completion meant that we were unable to prune the `false` edge (Boolean CFG splitting).
1 parent 8d7ea2f commit f91e460

14 files changed

Lines changed: 618 additions & 441 deletions

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

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ module ControlFlow {
736736
TLastRecBooleanNegationCompletion() or
737737
TLastRecNonBooleanCompletion() or
738738
TLastRecBreakCompletion() or
739+
TLastRecNonBreakCompletion() or
739740
TLastRecSwitchAbnormalCompletion() or
740741
TLastRecInvalidOperationException() or
741742
TLastRecNonContinueCompletion() or
@@ -941,7 +942,7 @@ module ControlFlow {
941942
// Last statement exits with any non-break completion
942943
exists(int last | last = max(int i | exists(ss.getStmt(i))) |
943944
result = ss.getStmt(last) and
944-
c = TRec(TLastRecSpecificNegCompletion(any(BreakCompletion bc)))
945+
c = TRec(TLastRecNonBreakCompletion())
945946
)
946947
)
947948
or
@@ -1098,7 +1099,7 @@ module ControlFlow {
10981099
or
10991100
result = lastRecSpecific(cfe, c, c)
11001101
or
1101-
exists(TLastRecComputation rec, Completion c0 | result = lastRec(cfe, c0, rec) |
1102+
exists(TLastRecComputation rec, Completion c0 | result = lastRec(rec, cfe, c0) |
11021103
rec = TLastRecSpecificNegCompletion(any(Completion c1 | c1 != c0)) and
11031104
c = c0
11041105
or
@@ -1109,7 +1110,7 @@ module ControlFlow {
11091110
c = c0
11101111
or
11111112
rec = TLastRecAbnormalCompletion() and
1112-
not c0 instanceof NormalCompletion and
1113+
c0 instanceof AbnormalCompletion and
11131114
c = c0
11141115
or
11151116
rec = TLastRecBooleanNegationCompletion() and
@@ -1128,6 +1129,10 @@ module ControlFlow {
11281129
c0 instanceof BreakCompletion and
11291130
c instanceof BreakNormalCompletion
11301131
or
1132+
rec = TLastRecNonBreakCompletion() and
1133+
not c0 instanceof BreakCompletion and
1134+
c = c0
1135+
or
11311136
rec = TLastRecSwitchAbnormalCompletion() and
11321137
not c instanceof BreakCompletion and
11331138
not c instanceof NormalCompletion and
@@ -1137,10 +1142,14 @@ module ControlFlow {
11371142
or
11381143
rec = TLastRecInvalidOperationException() and
11391144
(c0.(MatchingCompletion).isNonMatch() or c0 instanceof FalseCompletion) and
1140-
c
1141-
.(ThrowCompletion)
1142-
.getExceptionClass()
1143-
.hasQualifiedName("System.InvalidOperationException")
1145+
c = any(InheritedCompletion ic |
1146+
ic.getUnderlyingCompletion() = c0 and
1147+
ic
1148+
.getInheritedCompletion()
1149+
.(ThrowCompletionDirect)
1150+
.getExceptionClass()
1151+
.hasQualifiedName("System.InvalidOperationException")
1152+
)
11441153
or
11451154
rec = TLastRecNonContinueCompletion() and
11461155
not c0 instanceof BreakCompletion and
@@ -1156,16 +1165,30 @@ module ControlFlow {
11561165
or
11571166
// Last `catch` clause inherits throw completions from the `try` block,
11581167
// when the clause does not match
1159-
exists(SpecificCatchClause scc |
1168+
exists(SpecificCatchClause scc, ThrowCompletion tc |
11601169
scc = cfe and
11611170
scc.isLast() and
1162-
throwMayBeUncaught(scc, c)
1171+
throwMayBeUncaught(scc, tc)
11631172
|
11641173
// Incompatible exception type: clause itself
1165-
result = scc
1174+
result = scc and
1175+
exists(MatchingCompletion mc |
1176+
mc.isNonMatch() and
1177+
mc.isValidFor(scc) and
1178+
c = any(InheritedCompletion ic |
1179+
ic.getUnderlyingCompletion() = mc and
1180+
ic.getInheritedCompletion() = tc.getInheritedCompletion()
1181+
)
1182+
)
11661183
or
11671184
// Incompatible filter
1168-
result = lastSpecificCatchClauseFilterClause(scc)
1185+
exists(FalseCompletion fc |
1186+
result = lastSpecificCatchClauseFilterClause(scc, fc) and
1187+
c = any(InheritedCompletion ic |
1188+
ic.getUnderlyingCompletion() = fc and
1189+
ic.getInheritedCompletion() = tc.getInheritedCompletion()
1190+
)
1191+
)
11691192
)
11701193
or
11711194
cfe = any(TryStmt ts |
@@ -1187,8 +1210,12 @@ module ControlFlow {
11871210
exists(getBlockOrCatchFinallyPred(ts, any(NormalCompletion nc))) and
11881211
c = c0
11891212
or
1190-
exists(getBlockOrCatchFinallyPred(ts, c)) and
1191-
not c instanceof NormalCompletion
1213+
exists(AbnormalCompletion ac, InheritedCompletion ic |
1214+
c = ic and
1215+
exists(getBlockOrCatchFinallyPred(ts, ac)) and
1216+
ac.getInheritedCompletion() = ic.getInheritedCompletion() and
1217+
ic.getUnderlyingCompletion() = c0
1218+
)
11921219
)
11931220
)
11941221
)
@@ -1201,7 +1228,7 @@ module ControlFlow {
12011228
*/
12021229
pragma[nomagic]
12031230
private ControlFlowElement lastRec(
1204-
ControlFlowElement cfe, Completion c, TLastRecComputation rec
1231+
TLastRecComputation rec, ControlFlowElement cfe, Completion c
12051232
) {
12061233
result = last(lastNonRec(cfe, TRec(rec)), c)
12071234
}
@@ -1210,7 +1237,7 @@ module ControlFlow {
12101237
private ControlFlowElement lastRecSpecific(
12111238
ControlFlowElement cfe, Completion c1, Completion c2
12121239
) {
1213-
result = lastRec(cfe, c1, TLastRecSpecificCompletion(c2))
1240+
result = lastRec(TLastRecSpecificCompletion(c2), cfe, c1)
12141241
}
12151242

12161243
pragma[nomagic]
@@ -1234,8 +1261,10 @@ module ControlFlow {
12341261
result = last(cc.getBlock(), c)
12351262
}
12361263

1237-
private ControlFlowElement lastSpecificCatchClauseFilterClause(SpecificCatchClause scc) {
1238-
result = last(scc.getFilterClause(), _)
1264+
private ControlFlowElement lastSpecificCatchClauseFilterClause(
1265+
SpecificCatchClause scc, Completion c
1266+
) {
1267+
result = last(scc.getFilterClause(), c)
12391268
}
12401269

12411270
/**

0 commit comments

Comments
 (0)