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

Skip to content

Commit 0290c79

Browse files
authored
Merge pull request #1486 from hvitved/csharp/inherited-completions
Approved by calumgrant
2 parents 298aa92 + 349e0e8 commit 0290c79

19 files changed

Lines changed: 1455 additions & 666 deletions

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

Lines changed: 73 additions & 35 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
@@ -1113,12 +1114,24 @@ module ControlFlow {
11131114
c = c0
11141115
or
11151116
rec = TLastRecBooleanNegationCompletion() and
1116-
c = any(BooleanCompletion bc |
1117-
c0 = any(BooleanCompletion bc0 |
1118-
bc.getOuterValue() = bc0.getOuterValue().booleanNot() and
1119-
bc.getInnerValue() = bc0.getInnerValue()
1120-
)
1121-
)
1117+
(
1118+
c = any(NestedCompletion nc |
1119+
nc.getInnerCompletion() = c0 and
1120+
nc.getOuterCompletion().(BooleanCompletion).getValue() = c0
1121+
.(BooleanCompletion)
1122+
.getValue()
1123+
.booleanNot()
1124+
)
1125+
or
1126+
c = any(BooleanCompletion bc |
1127+
bc.getValue() = c0
1128+
.(NestedCompletion)
1129+
.getInnerCompletion()
1130+
.(BooleanCompletion)
1131+
.getValue() and
1132+
not bc instanceof NestedCompletion
1133+
)
1134+
)
11221135
or
11231136
rec = TLastRecNonBooleanCompletion() and
11241137
not c0 instanceof BooleanCompletion and
@@ -1128,6 +1141,10 @@ module ControlFlow {
11281141
c0 instanceof BreakCompletion and
11291142
c instanceof BreakNormalCompletion
11301143
or
1144+
rec = TLastRecNonBreakCompletion() and
1145+
not c0 instanceof BreakCompletion and
1146+
c = c0
1147+
or
11311148
rec = TLastRecSwitchAbnormalCompletion() and
11321149
not c instanceof BreakCompletion and
11331150
not c instanceof NormalCompletion and
@@ -1137,10 +1154,14 @@ module ControlFlow {
11371154
or
11381155
rec = TLastRecInvalidOperationException() and
11391156
(c0.(MatchingCompletion).isNonMatch() or c0 instanceof FalseCompletion) and
1140-
c
1141-
.(ThrowCompletion)
1142-
.getExceptionClass()
1143-
.hasQualifiedName("System.InvalidOperationException")
1157+
c = any(NestedCompletion nc |
1158+
nc.getInnerCompletion() = c0 and
1159+
nc
1160+
.getOuterCompletion()
1161+
.(ThrowCompletion)
1162+
.getExceptionClass()
1163+
.hasQualifiedName("System.InvalidOperationException")
1164+
)
11441165
or
11451166
rec = TLastRecNonContinueCompletion() and
11461167
not c0 instanceof BreakCompletion and
@@ -1156,16 +1177,30 @@ module ControlFlow {
11561177
or
11571178
// Last `catch` clause inherits throw completions from the `try` block,
11581179
// when the clause does not match
1159-
exists(SpecificCatchClause scc |
1180+
exists(SpecificCatchClause scc, ThrowCompletion tc |
11601181
scc = cfe and
11611182
scc.isLast() and
1162-
throwMayBeUncaught(scc, c)
1183+
throwMayBeUncaught(scc, tc)
11631184
|
11641185
// Incompatible exception type: clause itself
1165-
result = scc
1186+
result = scc and
1187+
exists(MatchingCompletion mc |
1188+
mc.isNonMatch() and
1189+
mc.isValidFor(scc) and
1190+
c = any(NestedCompletion nc |
1191+
nc.getInnerCompletion() = mc and
1192+
nc.getOuterCompletion() = tc.getOuterCompletion()
1193+
)
1194+
)
11661195
or
11671196
// Incompatible filter
1168-
result = lastSpecificCatchClauseFilterClause(scc)
1197+
exists(FalseCompletion fc |
1198+
result = lastSpecificCatchClauseFilterClause(scc, fc) and
1199+
c = any(NestedCompletion nc |
1200+
nc.getInnerCompletion() = fc and
1201+
nc.getOuterCompletion() = tc.getOuterCompletion()
1202+
)
1203+
)
11691204
)
11701205
or
11711206
cfe = any(TryStmt ts |
@@ -1179,18 +1214,13 @@ module ControlFlow {
11791214
c instanceof ExitCompletion
11801215
)
11811216
or
1182-
// If the `finally` block completes normally, it resumes any non-normal
1217+
result = lastTryStmtFinally(ts, c, any(NormalCompletion nc))
1218+
or
1219+
// If the `finally` block completes normally, it inherits any non-normal
11831220
// completion that was current before the `finally` block was entered
1184-
exists(NormalCompletion c0 |
1185-
result = lastTryStmtFinally(ts, c0) and
1186-
(
1187-
exists(getBlockOrCatchFinallyPred(ts, any(NormalCompletion nc))) and
1188-
c = c0
1189-
or
1190-
exists(getBlockOrCatchFinallyPred(ts, c)) and
1191-
not c instanceof NormalCompletion
1221+
c = any(NestedCompletion nc |
1222+
result = lastTryStmtFinally(ts, nc.getInnerCompletion(), nc.getOuterCompletion())
11921223
)
1193-
)
11941224
)
11951225
}
11961226

@@ -1201,7 +1231,7 @@ module ControlFlow {
12011231
*/
12021232
pragma[nomagic]
12031233
private ControlFlowElement lastRec(
1204-
ControlFlowElement cfe, Completion c, TLastRecComputation rec
1234+
TLastRecComputation rec, ControlFlowElement cfe, Completion c
12051235
) {
12061236
result = last(lastNonRec(cfe, TRec(rec)), c)
12071237
}
@@ -1210,19 +1240,14 @@ module ControlFlow {
12101240
private ControlFlowElement lastRecSpecific(
12111241
ControlFlowElement cfe, Completion c1, Completion c2
12121242
) {
1213-
result = lastRec(cfe, c1, TLastRecSpecificCompletion(c2))
1243+
result = lastRec(TLastRecSpecificCompletion(c2), cfe, c1)
12141244
}
12151245

12161246
pragma[nomagic]
12171247
private ControlFlowElement lastTryStmtBlock(TryStmt ts, Completion c) {
12181248
result = last(ts.getBlock(), c)
12191249
}
12201250

1221-
pragma[nomagic]
1222-
private ControlFlowElement lastTryStmtFinally(TryStmt ts, Completion c) {
1223-
result = last(ts.getFinally(), c)
1224-
}
1225-
12261251
pragma[nomagic]
12271252
private ControlFlowElement lastLastCatchClause(CatchClause cc, Completion c) {
12281253
cc.isLast() and
@@ -1234,8 +1259,10 @@ module ControlFlow {
12341259
result = last(cc.getBlock(), c)
12351260
}
12361261

1237-
private ControlFlowElement lastSpecificCatchClauseFilterClause(SpecificCatchClause scc) {
1238-
result = last(scc.getFilterClause(), _)
1262+
private ControlFlowElement lastSpecificCatchClauseFilterClause(
1263+
SpecificCatchClause scc, Completion c
1264+
) {
1265+
result = last(scc.getFilterClause(), c)
12391266
}
12401267

12411268
/**
@@ -1263,6 +1290,17 @@ module ControlFlow {
12631290
result = lastLastCatchClause(ts.getACatchClause(), c)
12641291
}
12651292

1293+
pragma[nomagic]
1294+
private ControlFlowElement lastTryStmtFinally0(TryStmt ts, Completion c) {
1295+
result = last(ts.getFinally(), c)
1296+
}
1297+
1298+
pragma[nomagic]
1299+
ControlFlowElement lastTryStmtFinally(TryStmt ts, NormalCompletion finally, Completion outer) {
1300+
result = lastTryStmtFinally0(ts, finally) and
1301+
exists(getBlockOrCatchFinallyPred(ts, any(Completion c0 | outer = c0.getOuterCompletion())))
1302+
}
1303+
12661304
/**
12671305
* Holds if the `try` block that catch clause `last` belongs to may throw an
12681306
* exception of type `c`, where no `catch` clause is guaranteed to catch it.

0 commit comments

Comments
 (0)