diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll index 072f611a45aa..072eb63b2a9b 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll @@ -219,7 +219,9 @@ module Ast implements AstSig { final private class FinalCatchClause = CS::CatchClause; class CatchClause extends FinalCatchClause { - AstNode getVariable() { result = this.(CS::SpecificCatchClause).getVariableDeclExpr() } + AstNode getPattern() { result = this.(CS::SpecificCatchClause).getVariableDeclExpr() } + + AstNode getVariable() { none() } Expr getCondition() { result = this.getFilterClause() } diff --git a/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected b/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected index 4493882fa476..5eacd99b7e6f 100644 --- a/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected +++ b/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected @@ -336,11 +336,12 @@ | patterns.cs:142:26:142:34 | { ... } | patterns.cs:142:26:142:34 | After { ... } | semmle.label | successor | | patterns.cs:142:31:142:32 | 10 | patterns.cs:142:26:142:34 | { ... } | semmle.label | successor | | patterns.cs:142:41:142:41 | 6 | patterns.cs:136:17:143:13 | After ... switch { ... } | semmle.label | successor | -| patterns.cs:145:9:148:9 | After catch (...) {...} [match] | patterns.cs:145:41:145:42 | InvalidOperationException ex | semmle.label | successor | | patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | patterns.cs:123:10:123:21 | Exceptional Exit | semmle.label | exception | -| patterns.cs:145:9:148:9 | catch (...) {...} | patterns.cs:145:9:148:9 | After catch (...) {...} [match] | semmle.label | match | -| patterns.cs:145:9:148:9 | catch (...) {...} | patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | semmle.label | no-match | -| patterns.cs:145:41:145:42 | InvalidOperationException ex | patterns.cs:146:9:148:9 | {...} | semmle.label | successor | +| patterns.cs:145:9:148:9 | catch (...) {...} | patterns.cs:145:41:145:42 | InvalidOperationException ex | semmle.label | successor | +| patterns.cs:145:41:145:42 | After InvalidOperationException ex [match] | patterns.cs:146:9:148:9 | {...} | semmle.label | successor | +| patterns.cs:145:41:145:42 | After InvalidOperationException ex [no-match] | patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | semmle.label | no-match | +| patterns.cs:145:41:145:42 | InvalidOperationException ex | patterns.cs:145:41:145:42 | After InvalidOperationException ex [match] | semmle.label | match | +| patterns.cs:145:41:145:42 | InvalidOperationException ex | patterns.cs:145:41:145:42 | After InvalidOperationException ex [no-match] | semmle.label | no-match | | patterns.cs:146:9:148:9 | After {...} | patterns.cs:134:9:148:9 | After try {...} ... | semmle.label | successor | | patterns.cs:146:9:148:9 | {...} | patterns.cs:147:13:147:51 | ...; | semmle.label | successor | | patterns.cs:147:13:147:50 | After call to method WriteLine | patterns.cs:147:13:147:51 | After ...; | semmle.label | successor | diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index 142f9f61e569..7390be9cb3cf 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -138,7 +138,9 @@ private module Ast implements AstSig { final private class FinalCatchClause = J::CatchClause; class CatchClause extends FinalCatchClause { - AstNode getVariable() { result = super.getVariable() } + AstNode getPattern() { result = super.getVariable() } + + AstNode getVariable() { none() } Expr getCondition() { none() } diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected index 484fb5ea042e..a3c7b11eb217 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected @@ -235,15 +235,16 @@ | Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... | | Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 | | Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... | -| Test.kt:86:4:88:2 | After catch (...) [match] | 0 | Test.kt:86:4:88:2 | After catch (...) [match] | -| Test.kt:86:4:88:2 | After catch (...) [match] | 1 | Test.kt:86:11:86:31 | e | -| Test.kt:86:4:88:2 | After catch (...) [match] | 2 | Test.kt:86:34:88:2 | { ... } | -| Test.kt:86:4:88:2 | After catch (...) [match] | 3 | Test.kt:87:3:87:10 | Before return ... | -| Test.kt:86:4:88:2 | After catch (...) [match] | 4 | Test.kt:87:10:87:10 | 2 | -| Test.kt:86:4:88:2 | After catch (...) [match] | 5 | Test.kt:87:3:87:10 | return ... | -| Test.kt:86:4:88:2 | After catch (...) [no-match] | 0 | Test.kt:86:4:88:2 | After catch (...) [no-match] | -| Test.kt:86:4:88:2 | After catch (...) [no-match] | 1 | Test.kt:82:1:89:1 | Exceptional Exit | | Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) | +| Test.kt:86:4:88:2 | catch (...) | 1 | Test.kt:86:11:86:31 | e | +| Test.kt:86:11:86:31 | After e [match] | 0 | Test.kt:86:11:86:31 | After e [match] | +| Test.kt:86:11:86:31 | After e [match] | 1 | Test.kt:86:34:88:2 | { ... } | +| Test.kt:86:11:86:31 | After e [match] | 2 | Test.kt:87:3:87:10 | Before return ... | +| Test.kt:86:11:86:31 | After e [match] | 3 | Test.kt:87:10:87:10 | 2 | +| Test.kt:86:11:86:31 | After e [match] | 4 | Test.kt:87:3:87:10 | return ... | +| Test.kt:86:11:86:31 | After e [no-match] | 0 | Test.kt:86:11:86:31 | After e [no-match] | +| Test.kt:86:11:86:31 | After e [no-match] | 1 | Test.kt:86:4:88:2 | After catch (...) [no-match] | +| Test.kt:86:11:86:31 | After e [no-match] | 2 | Test.kt:82:1:89:1 | Exceptional Exit | | Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry | | Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } | | Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... | @@ -262,15 +263,16 @@ | Test.kt:93:12:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... | | Test.kt:93:12:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 | | Test.kt:93:12:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... | -| Test.kt:95:4:97:2 | After catch (...) [match] | 0 | Test.kt:95:4:97:2 | After catch (...) [match] | -| Test.kt:95:4:97:2 | After catch (...) [match] | 1 | Test.kt:95:11:95:33 | e | -| Test.kt:95:4:97:2 | After catch (...) [match] | 2 | Test.kt:95:36:97:2 | { ... } | -| Test.kt:95:4:97:2 | After catch (...) [match] | 3 | Test.kt:96:3:96:10 | Before return ... | -| Test.kt:95:4:97:2 | After catch (...) [match] | 4 | Test.kt:96:10:96:10 | 2 | -| Test.kt:95:4:97:2 | After catch (...) [match] | 5 | Test.kt:96:3:96:10 | return ... | -| Test.kt:95:4:97:2 | After catch (...) [no-match] | 0 | Test.kt:95:4:97:2 | After catch (...) [no-match] | -| Test.kt:95:4:97:2 | After catch (...) [no-match] | 1 | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) | +| Test.kt:95:4:97:2 | catch (...) | 1 | Test.kt:95:11:95:33 | e | +| Test.kt:95:11:95:33 | After e [match] | 0 | Test.kt:95:11:95:33 | After e [match] | +| Test.kt:95:11:95:33 | After e [match] | 1 | Test.kt:95:36:97:2 | { ... } | +| Test.kt:95:11:95:33 | After e [match] | 2 | Test.kt:96:3:96:10 | Before return ... | +| Test.kt:95:11:95:33 | After e [match] | 3 | Test.kt:96:10:96:10 | 2 | +| Test.kt:95:11:95:33 | After e [match] | 4 | Test.kt:96:3:96:10 | return ... | +| Test.kt:95:11:95:33 | After e [no-match] | 0 | Test.kt:95:11:95:33 | After e [no-match] | +| Test.kt:95:11:95:33 | After e [no-match] | 1 | Test.kt:95:4:97:2 | After catch (...) [no-match] | +| Test.kt:95:11:95:33 | After e [no-match] | 2 | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry | | Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } | | Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | ; | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected index bac6b7224475..4e66ae0cd04f 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected @@ -32,17 +32,17 @@ | Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x | | Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) | -| Test.kt:82:21:89:1 | { ... } | Test.kt:86:11:86:31 | e | +| Test.kt:82:21:89:1 | { ... } | Test.kt:86:34:88:2 | { ... } | | Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit | -| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:34:88:2 | { ... } | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x | | Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) | -| Test.kt:91:22:98:1 | { ... } | Test.kt:95:11:95:33 | e | +| Test.kt:91:22:98:1 | { ... } | Test.kt:95:36:97:2 | { ... } | | Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit | -| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:36:97:2 | { ... } | | Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected index 0596f159e223..25b51acefc4a 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected @@ -20,16 +20,16 @@ | Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) | | Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit | -| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e | -| Test.kt:86:11:86:31 | e | Test.kt:82:1:89:1 | Normal Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:34:88:2 | { ... } | +| Test.kt:86:34:88:2 | { ... } | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit | | Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x | | Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) | | Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit | -| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e | -| Test.kt:95:11:95:33 | e | Test.kt:91:1:98:1 | Normal Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:36:97:2 | { ... } | +| Test.kt:95:36:97:2 | { ... } | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected index 8f9cce281606..291c07f68571 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected @@ -136,8 +136,8 @@ | Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause | | Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method | | Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt | -| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:82:1:89:1 | Exceptional Exit | Method | | Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | +| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:82:1:89:1 | Exceptional Exit | Method | | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt | | Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral | | Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method | @@ -155,8 +155,8 @@ | Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause | | Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method | | Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt | -| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:91:1:98:1 | Exceptional Exit | Method | | Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | +| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:91:1:98:1 | Exceptional Exit | Method | | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt | | Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral | | Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method | diff --git a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected index 54bd6b9388f2..de98d238e402 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected +++ b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected @@ -14,8 +14,8 @@ | MultiCatch.java:12:11:12:27 | new IOException(...) | MultiCatch.java:12:5:12:28 | throw ... | | MultiCatch.java:14:5:14:29 | throw ... | MultiCatch.java:15:5:15:37 | catch (...) | | MultiCatch.java:14:11:14:28 | new SQLException(...) | MultiCatch.java:14:5:14:29 | throw ... | -| MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:7:14:7:23 | Exceptional Exit | | MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:15:36:15:36 | e | +| MultiCatch.java:15:36:15:36 | e | MultiCatch.java:7:14:7:23 | Exceptional Exit | | MultiCatch.java:15:36:15:36 | e | MultiCatch.java:16:3:19:3 | { ... } | | MultiCatch.java:16:3:19:3 | { ... } | MultiCatch.java:17:4:17:23 | ; | | MultiCatch.java:17:4:17:4 | e | MultiCatch.java:17:4:17:22 | printStackTrace(...) | @@ -41,8 +41,8 @@ | MultiCatch.java:29:11:29:28 | new SQLException(...) | MultiCatch.java:29:5:29:29 | throw ... | | MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) | | MultiCatch.java:30:10:30:24 | new Exception(...) | MultiCatch.java:30:4:30:25 | throw ... | -| MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:22:14:22:24 | Exceptional Exit | | MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:31:36:31:36 | e | +| MultiCatch.java:31:36:31:36 | e | MultiCatch.java:22:14:22:24 | Exceptional Exit | | MultiCatch.java:31:36:31:36 | e | MultiCatch.java:32:3:32:4 | { ... } | | MultiCatch.java:32:3:32:4 | { ... } | MultiCatch.java:22:14:22:24 | Normal Exit | | MultiCatch.java:35:14:35:26 | Entry | MultiCatch.java:36:2:42:2 | { ... } | diff --git a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected index 6889eb8da32d..3151eb07f7cb 100644 --- a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected +++ b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected @@ -28,8 +28,8 @@ | CloseReaderTest.java:19:11:19:15 | stdin | CloseReaderTest.java:19:11:19:26 | readLine(...) | | CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:19:4:19:27 | return ... | | CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:20:5:20:26 | catch (...) | -| CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:9:23:9:34 | Exceptional Exit | | CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:20:24:20:25 | ex | +| CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:9:23:9:34 | Exceptional Exit | | CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:21:3:23:3 | { ... } | | CloseReaderTest.java:21:3:23:3 | { ... } | CloseReaderTest.java:22:11:22:14 | null | | CloseReaderTest.java:22:4:22:15 | return ... | CloseReaderTest.java:9:23:9:34 | Normal Exit | diff --git a/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected b/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected index 19fef193edba..574837742c05 100644 --- a/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected +++ b/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected @@ -50,16 +50,16 @@ | SchackTest.java:16:4:16:41 | ; | SchackTest.java:16:4:16:13 | System.out | | SchackTest.java:16:23:16:39 | "false successor" | SchackTest.java:16:4:16:40 | println(...) | | SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:17:16:17:16 | e | -| SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:19:5:19:17 | catch (...) | | SchackTest.java:17:16:17:16 | e | SchackTest.java:17:19:19:3 | { ... } | +| SchackTest.java:17:16:17:16 | e | SchackTest.java:19:5:19:17 | catch (...) | | SchackTest.java:17:19:19:3 | { ... } | SchackTest.java:18:4:18:41 | ; | | SchackTest.java:18:4:18:13 | System.out | SchackTest.java:18:23:18:39 | "false successor" | | SchackTest.java:18:4:18:40 | println(...) | SchackTest.java:21:13:23:3 | { ... } | | SchackTest.java:18:4:18:41 | ; | SchackTest.java:18:4:18:13 | System.out | | SchackTest.java:18:23:18:39 | "false successor" | SchackTest.java:18:4:18:40 | println(...) | | SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:19:16:19:16 | e | -| SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:21:13:23:3 | { ... } | | SchackTest.java:19:16:19:16 | e | SchackTest.java:19:19:21:3 | { ... } | +| SchackTest.java:19:16:19:16 | e | SchackTest.java:21:13:23:3 | { ... } | | SchackTest.java:19:19:21:3 | { ... } | SchackTest.java:20:4:20:74 | ; | | SchackTest.java:20:4:20:13 | System.out | SchackTest.java:20:23:20:72 | "successor (but neither true nor false successor)" | | SchackTest.java:20:4:20:73 | println(...) | SchackTest.java:21:13:23:3 | { ... } | diff --git a/java/ql/test/library-tests/successors/TestThrow/TestSucc.expected b/java/ql/test/library-tests/successors/TestThrow/TestSucc.expected index 3ed406a0a71a..e673cf0bcbe5 100644 --- a/java/ql/test/library-tests/successors/TestThrow/TestSucc.expected +++ b/java/ql/test/library-tests/successors/TestThrow/TestSucc.expected @@ -18,8 +18,8 @@ | TestThrow.java:20:10:20:31 | new RuntimeException(...) | TestThrow.java:20:4:20:32 | throw ... | | TestThrow.java:20:10:20:31 | new RuntimeException(...) | TestThrow.java:21:5:21:30 | catch (...) | | TestThrow.java:21:5:21:30 | catch (...) | TestThrow.java:21:29:21:29 | e | -| TestThrow.java:21:5:21:30 | catch (...) | TestThrow.java:24:5:24:23 | catch (...) | | TestThrow.java:21:29:21:29 | e | TestThrow.java:22:3:24:3 | { ... } | +| TestThrow.java:21:29:21:29 | e | TestThrow.java:24:5:24:23 | catch (...) | | TestThrow.java:22:3:24:3 | { ... } | TestThrow.java:23:4:23:9 | ; | | TestThrow.java:23:4:23:4 | z | TestThrow.java:23:8:23:8 | 1 | | TestThrow.java:23:4:23:8 | ...=... | TestThrow.java:29:3:29:9 | ; | @@ -71,8 +71,8 @@ | TestThrow.java:44:5:44:13 | thrower(...) | TestThrow.java:50:3:52:3 | { ... } | | TestThrow.java:44:5:44:14 | ; | TestThrow.java:44:5:44:13 | thrower(...) | | TestThrow.java:46:5:46:30 | catch (...) | TestThrow.java:46:29:46:29 | e | -| TestThrow.java:46:5:46:30 | catch (...) | TestThrow.java:50:3:52:3 | { ... } | | TestThrow.java:46:29:46:29 | e | TestThrow.java:47:3:49:3 | { ... } | +| TestThrow.java:46:29:46:29 | e | TestThrow.java:50:3:52:3 | { ... } | | TestThrow.java:47:3:49:3 | { ... } | TestThrow.java:48:4:48:9 | ; | | TestThrow.java:48:4:48:4 | z | TestThrow.java:48:8:48:8 | 1 | | TestThrow.java:48:4:48:8 | ...=... | TestThrow.java:50:3:52:3 | { ... } | @@ -113,8 +113,8 @@ | TestThrow.java:67:5:67:13 | thrower(...) | TestThrow.java:69:5:69:30 | catch (...) | | TestThrow.java:67:5:67:13 | thrower(...) | TestThrow.java:74:3:74:9 | ; | | TestThrow.java:67:5:67:14 | ; | TestThrow.java:67:5:67:13 | thrower(...) | -| TestThrow.java:69:5:69:30 | catch (...) | TestThrow.java:15:14:15:14 | Exceptional Exit | | TestThrow.java:69:5:69:30 | catch (...) | TestThrow.java:69:29:69:29 | e | +| TestThrow.java:69:29:69:29 | e | TestThrow.java:15:14:15:14 | Exceptional Exit | | TestThrow.java:69:29:69:29 | e | TestThrow.java:70:3:72:3 | { ... } | | TestThrow.java:70:3:72:3 | { ... } | TestThrow.java:71:4:71:9 | ; | | TestThrow.java:71:4:71:4 | z | TestThrow.java:71:8:71:8 | 1 | @@ -171,8 +171,8 @@ | TestThrow.java:97:28:97:36 | "Foo bar" | TestThrow.java:97:39:97:42 | null | | TestThrow.java:97:39:97:42 | null | TestThrow.java:97:12:97:43 | new IOException(...) | | TestThrow.java:99:6:99:31 | catch (...) | TestThrow.java:99:30:99:30 | e | -| TestThrow.java:99:6:99:31 | catch (...) | TestThrow.java:119:5:119:25 | catch (...) | | TestThrow.java:99:30:99:30 | e | TestThrow.java:100:4:102:4 | { ... } | +| TestThrow.java:99:30:99:30 | e | TestThrow.java:119:5:119:25 | catch (...) | | TestThrow.java:100:4:102:4 | { ... } | TestThrow.java:101:5:101:10 | ; | | TestThrow.java:101:5:101:5 | z | TestThrow.java:101:9:101:9 | 1 | | TestThrow.java:101:5:101:9 | ...=... | TestThrow.java:103:4:118:4 | try ... | @@ -216,8 +216,8 @@ | TestThrow.java:116:28:116:36 | "Foo bar" | TestThrow.java:116:39:116:42 | null | | TestThrow.java:116:39:116:42 | null | TestThrow.java:116:12:116:43 | new IOException(...) | | TestThrow.java:119:5:119:25 | catch (...) | TestThrow.java:119:24:119:24 | e | -| TestThrow.java:119:5:119:25 | catch (...) | TestThrow.java:124:3:126:3 | { ... } | | TestThrow.java:119:24:119:24 | e | TestThrow.java:120:3:122:3 | { ... } | +| TestThrow.java:119:24:119:24 | e | TestThrow.java:124:3:126:3 | { ... } | | TestThrow.java:120:3:122:3 | { ... } | TestThrow.java:121:4:121:9 | ; | | TestThrow.java:121:4:121:4 | z | TestThrow.java:121:8:121:8 | 2 | | TestThrow.java:121:4:121:8 | ...=... | TestThrow.java:124:3:126:3 | { ... } | diff --git a/java/ql/test/library-tests/successors/TestTryCatch/TestSucc.expected b/java/ql/test/library-tests/successors/TestTryCatch/TestSucc.expected index 7769fd9d5b3d..f3759792eaca 100644 --- a/java/ql/test/library-tests/successors/TestTryCatch/TestSucc.expected +++ b/java/ql/test/library-tests/successors/TestTryCatch/TestSucc.expected @@ -105,8 +105,8 @@ | TestTryCatch.java:34:9:34:9 | y | TestTryCatch.java:34:13:34:13 | 1 | | TestTryCatch.java:34:9:34:13 | ... + ... | TestTryCatch.java:34:5:34:13 | ...=... | | TestTryCatch.java:34:13:34:13 | 1 | TestTryCatch.java:34:9:34:13 | ... + ... | -| TestTryCatch.java:35:6:35:31 | catch (...) | TestTryCatch.java:4:14:4:14 | Exceptional Exit | | TestTryCatch.java:35:6:35:31 | catch (...) | TestTryCatch.java:35:30:35:30 | e | +| TestTryCatch.java:35:30:35:30 | e | TestTryCatch.java:4:14:4:14 | Exceptional Exit | | TestTryCatch.java:35:30:35:30 | e | TestTryCatch.java:36:4:40:4 | { ... } | | TestTryCatch.java:36:4:40:4 | { ... } | TestTryCatch.java:37:5:37:14 | var ...; | | TestTryCatch.java:37:5:37:14 | var ...; | TestTryCatch.java:37:13:37:13 | 1 | diff --git a/java/ql/test/library-tests/successors/TestTryWithResources/TestSucc.expected b/java/ql/test/library-tests/successors/TestTryWithResources/TestSucc.expected index e9dabd746f1a..f8fe1c798db7 100644 --- a/java/ql/test/library-tests/successors/TestTryWithResources/TestSucc.expected +++ b/java/ql/test/library-tests/successors/TestTryWithResources/TestSucc.expected @@ -28,8 +28,8 @@ | TestTryWithResources.java:10:4:10:32 | ; | TestTryWithResources.java:10:4:10:13 | System.out | | TestTryWithResources.java:10:23:10:30 | "worked" | TestTryWithResources.java:10:4:10:31 | println(...) | | TestTryWithResources.java:11:5:11:35 | catch (...) | TestTryWithResources.java:11:34:11:34 | e | -| TestTryWithResources.java:11:5:11:35 | catch (...) | TestTryWithResources.java:13:13:15:3 | { ... } | | TestTryWithResources.java:11:34:11:34 | e | TestTryWithResources.java:11:37:13:3 | { ... } | +| TestTryWithResources.java:11:34:11:34 | e | TestTryWithResources.java:13:13:15:3 | { ... } | | TestTryWithResources.java:11:37:13:3 | { ... } | TestTryWithResources.java:12:4:12:40 | ; | | TestTryWithResources.java:12:4:12:13 | System.out | TestTryWithResources.java:12:23:12:38 | "file not found" | | TestTryWithResources.java:12:4:12:39 | println(...) | TestTryWithResources.java:13:13:15:3 | { ... } | diff --git a/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll b/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll index 71d22c416ea8..da4e36b3e36b 100644 --- a/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll +++ b/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll @@ -226,13 +226,24 @@ signature module AstSig { /** A catch clause in a try statement. */ class CatchClause extends AstNode { - /** Gets the variable declared by this catch clause. */ + /** + * Gets the pattern matched by this catch clause, if any. + * + * A catch clause without a pattern is a catch-all that matches any exception. + */ + AstNode getPattern(); + + /** + * Gets the variable declared by this catch clause, if any. + * + * Some languages include the variable binding as part of the pattern. + */ AstNode getVariable(); /** Gets the guard condition of this catch clause, if any. */ Expr getCondition(); - /** Gets the body of this catch clause. */ + /** Gets the body of this catch clause, if any. */ Stmt getBody(); } @@ -504,7 +515,7 @@ module Make0 Ast> { default Parameter callableGetParameter(Callable c, CallableContext ctx, int index) { none() } /** Holds if catch clause `catch` catches all exceptions. */ - default predicate catchAll(CatchClause catch) { none() } + default predicate catchAll(CatchClause catch) { not exists(catch.getPattern()) } /** * Holds if case `c` matches all possible values, for example, if it is a @@ -636,6 +647,8 @@ module Make0 Ast> { ( n instanceof CatchClause or + exists(CatchClause catch | n = catch.getPattern()) + or n instanceof Case or n = any(Case case).getPattern(_) @@ -658,6 +671,8 @@ module Make0 Ast> { not inConditionalContext(n, _) } + private string catchClauseEmptyBodyTag() { result = "[CatchClauseEmptyBody]" } + private string loopHeaderTag() { result = "[LoopHeader]" } private string patternMatchTrueTag() { result = "[MatchTrue]" } @@ -670,6 +685,13 @@ module Make0 Ast> { private predicate additionalNode(AstNode n, string tag, NormalSuccessor t) { Input1::additionalNode(n, tag, t) or + exists(CatchClause catch | + n = catch and + not exists(catch.getBody()) and + tag = catchClauseEmptyBodyTag() and + t instanceof DirectSuccessor + ) + or n instanceof LoopStmt and tag = loopHeaderTag() and t instanceof DirectSuccessor @@ -810,6 +832,12 @@ module Make0 Ast> { not exists(c.getPattern(i + 1)) and t.(MatchingSuccessor).getValue() = true ) + or + exists(CatchClause catch | + Input1::catchAll(catch) and + catch.getPattern() = n and + t.(MatchingSuccessor).getValue() = true + ) } private predicate hasCfg(AstNode n) { @@ -1415,6 +1443,18 @@ module Make0 Ast> { result = getBodyEntry(c, ctx) } + private PreControlFlowNode getBeforeCatchBody(CatchClause catch) { + if exists(catch.getBody()) + then result.isBefore(catch.getBody()) + else result.isAdditional(catch, catchClauseEmptyBodyTag()) + } + + private PreControlFlowNode getAfterCatchBody(CatchClause catch) { + if exists(catch.getBody()) + then result.isAfter(catch.getBody()) + else result.isAdditional(catch, catchClauseEmptyBodyTag()) + } + /** Holds if there is a local non-abrupt step from `n1` to `n2`. */ private predicate explicitStep(PreControlFlowNode n1, PreControlFlowNode n2) { Input2::step(n1, n2) @@ -1682,7 +1722,7 @@ module Make0 Ast> { n1.isAfter(getTryElse(trystmt)) and n2 = beforeFinally or - n1.isAfter(trystmt.getCatch(_).getBody()) and + n1 = getAfterCatchBody(trystmt.getCatch(_)) and n2 = beforeFinally ) or @@ -1696,13 +1736,15 @@ module Make0 Ast> { ) or exists(CatchClause catchclause | - exists(MatchingSuccessor t | - n1.isBefore(catchclause) and - n2.isAfterValue(catchclause, t) and - if Input1::catchAll(catchclause) then t.getValue() = true else any() - ) - or - exists(PreControlFlowNode beforeVar, PreControlFlowNode beforeCond | + exists( + PreControlFlowNode beforePattern, PreControlFlowNode beforeVar, + PreControlFlowNode beforeCond + | + ( + beforePattern.isBefore(catchclause.getPattern()) + or + not exists(catchclause.getPattern()) and beforePattern = beforeVar + ) and ( beforeVar.isBefore(catchclause.getVariable()) or @@ -1711,9 +1753,18 @@ module Make0 Ast> { ( beforeCond.isBefore(catchclause.getCondition()) or - not exists(catchclause.getCondition()) and beforeCond.isBefore(catchclause.getBody()) + not exists(catchclause.getCondition()) and + beforeCond = getBeforeCatchBody(catchclause) ) | + n1.isBefore(catchclause) and + n2 = beforePattern + or + exists(MatchingSuccessor t | + n1.isAfterValue(catchclause.getPattern(), t) and + if t.isMatch() then n2 = beforeVar else n2.isAfterValue(catchclause, t) + ) + or n1.isAfterValue(catchclause, any(MatchingSuccessor t | t.getValue() = true)) and n2 = beforeVar or @@ -1722,7 +1773,7 @@ module Make0 Ast> { ) or n1.isAfterTrue(catchclause.getCondition()) and - n2.isBefore(catchclause.getBody()) + n2 = getBeforeCatchBody(catchclause) or n1.isAfterFalse(catchclause.getCondition()) and n2.isAfterValue(catchclause, any(MatchingSuccessor t | t.getValue() = false))