Skip to content

Commit 8e546a3

Browse files
authored
Merge pull request #637 from hvitved/csharp/cfg/throwing-callable
C#: Fix a bug in `ThrowingCallable`
2 parents 12bc1fc + c887dc8 commit 8e546a3

File tree

12 files changed

+688
-569
lines changed

12 files changed

+688
-569
lines changed

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,28 +1871,32 @@ module ControlFlow {
18711871
}
18721872
}
18731873

1874+
private predicate directlyThrows(ThrowElement te, ThrowCompletion c) {
1875+
c.getExceptionClass() = te.getThrownExceptionType() and
1876+
// For stub implementations, there may exist proper implementations that are not seen
1877+
// during compilation, so we conservatively rule those out
1878+
not isStub(te)
1879+
}
1880+
18741881
private ControlFlowElement getAThrowingElement(ThrowCompletion c) {
18751882
c = result.(ThrowingCall).getACompletion()
18761883
or
1877-
result = any(ThrowElement te |
1878-
c.getExceptionClass() = te.getThrownExceptionType() and
1879-
// For stub implementations, there may exist proper implementations that are not seen
1880-
// during compilation, so we conservatively rule those out
1881-
not isStub(te)
1882-
)
1884+
directlyThrows(result, c)
18831885
or
18841886
result = getAThrowingStmt(c)
18851887
}
18861888

18871889
private Stmt getAThrowingStmt(ThrowCompletion c) {
1890+
directlyThrows(result, c)
1891+
or
18881892
result.(ExprStmt).getExpr() = getAThrowingElement(c)
18891893
or
18901894
result.(BlockStmt).getFirstStmt() = getAThrowingStmt(c)
18911895
or
18921896
exists(IfStmt ifStmt, ThrowCompletion c1, ThrowCompletion c2 |
18931897
result = ifStmt and
1894-
ifStmt.getThen() = getAThrowingElement(c1) and
1895-
ifStmt.getElse() = getAThrowingElement(c2) |
1898+
ifStmt.getThen() = getAThrowingStmt(c1) and
1899+
ifStmt.getElse() = getAThrowingStmt(c2) |
18961900
c = c1
18971901
or
18981902
c = c2

csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -187,28 +187,32 @@
187187
| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | 1 |
188188
| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | 2 |
189189
| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:13:49:19 | return ...; | 3 |
190-
| ExitMethods.cs:53:17:53:26 | enter ErrorMaybe | ExitMethods.cs:55:13:55:13 | access to parameter b | 4 |
191-
| ExitMethods.cs:53:17:53:26 | exit ErrorMaybe | ExitMethods.cs:53:17:53:26 | exit ErrorMaybe | 1 |
192-
| ExitMethods.cs:56:19:56:33 | object creation of type Exception | ExitMethods.cs:56:13:56:34 | throw ...; | 2 |
193-
| ExitMethods.cs:59:17:59:27 | enter ErrorAlways | ExitMethods.cs:61:13:61:13 | access to parameter b | 4 |
194-
| ExitMethods.cs:59:17:59:27 | exit ErrorAlways | ExitMethods.cs:59:17:59:27 | exit ErrorAlways | 1 |
195-
| ExitMethods.cs:62:19:62:33 | object creation of type Exception | ExitMethods.cs:62:13:62:34 | throw ...; | 2 |
196-
| ExitMethods.cs:64:41:64:43 | "b" | ExitMethods.cs:64:13:64:45 | throw ...; | 3 |
197-
| ExitMethods.cs:67:10:67:13 | enter Exit | ExitMethods.cs:67:10:67:13 | exit Exit | 6 |
198-
| ExitMethods.cs:72:10:72:18 | enter ExitInTry | ExitMethods.cs:72:10:72:18 | exit ExitInTry | 8 |
199-
| ExitMethods.cs:85:10:85:24 | enter ApplicationExit | ExitMethods.cs:85:10:85:24 | exit ApplicationExit | 5 |
200-
| ExitMethods.cs:90:13:90:21 | enter ThrowExpr | ExitMethods.cs:92:16:92:25 | ... != ... | 7 |
201-
| ExitMethods.cs:90:13:90:21 | exit ThrowExpr | ExitMethods.cs:90:13:90:21 | exit ThrowExpr | 1 |
202-
| ExitMethods.cs:92:29:92:29 | 1 | ExitMethods.cs:92:9:92:77 | return ...; | 5 |
203-
| ExitMethods.cs:92:69:92:75 | "input" | ExitMethods.cs:92:41:92:76 | throw ... | 3 |
204-
| ExitMethods.cs:95:16:95:34 | enter ExtensionMethodCall | ExitMethods.cs:97:16:97:30 | call to method Contains | 6 |
205-
| ExitMethods.cs:97:9:97:39 | return ...; | ExitMethods.cs:95:16:95:34 | exit ExtensionMethodCall | 2 |
206-
| ExitMethods.cs:97:34:97:34 | 0 | ExitMethods.cs:97:34:97:34 | 0 | 1 |
207-
| ExitMethods.cs:97:38:97:38 | 1 | ExitMethods.cs:97:38:97:38 | 1 | 1 |
208-
| ExitMethods.cs:100:17:100:32 | enter FailingAssertion | ExitMethods.cs:100:17:100:32 | exit FailingAssertion | 6 |
209-
| ExitMethods.cs:106:17:106:33 | enter FailingAssertion2 | ExitMethods.cs:106:17:106:33 | exit FailingAssertion2 | 6 |
210-
| ExitMethods.cs:112:10:112:20 | enter AssertFalse | ExitMethods.cs:112:10:112:20 | exit AssertFalse | 4 |
211-
| ExitMethods.cs:114:17:114:33 | enter FailingAssertion3 | ExitMethods.cs:114:17:114:33 | exit FailingAssertion3 | 7 |
190+
| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:53:10:53:11 | exit M7 | 5 |
191+
| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:59:10:59:11 | exit M8 | 5 |
192+
| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:67:13:67:13 | access to parameter b | 4 |
193+
| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | 1 |
194+
| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:13:68:34 | throw ...; | 2 |
195+
| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:73:13:73:13 | access to parameter b | 4 |
196+
| ExitMethods.cs:71:17:71:27 | exit ErrorAlways | ExitMethods.cs:71:17:71:27 | exit ErrorAlways | 1 |
197+
| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:13:74:34 | throw ...; | 2 |
198+
| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:13:76:45 | throw ...; | 3 |
199+
| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 | 5 |
200+
| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 | 4 |
201+
| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:86:10:86:13 | exit Exit | 6 |
202+
| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:91:10:91:18 | exit ExitInTry | 8 |
203+
| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:104:10:104:24 | exit ApplicationExit | 5 |
204+
| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:16:111:25 | ... != ... | 7 |
205+
| ExitMethods.cs:109:13:109:21 | exit ThrowExpr | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | 1 |
206+
| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:9:111:77 | return ...; | 5 |
207+
| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:41:111:76 | throw ... | 3 |
208+
| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:16:116:30 | call to method Contains | 6 |
209+
| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall | 2 |
210+
| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:34:116:34 | 0 | 1 |
211+
| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | 1 |
212+
| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | 6 |
213+
| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | 6 |
214+
| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | 4 |
215+
| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | 7 |
212216
| Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | exit ToInt32 | 6 |
213217
| Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | exit ToBool | 7 |
214218
| Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | exit CallToInt32 | 4 |

0 commit comments

Comments
 (0)