diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs index 30669aae78f..cc497ed0f49 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs @@ -25,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements { var type = Type.Create(Context, Context.GetType(Stmt.Declaration!.Type)); trapFile.catch_type(this, type.TypeRef, true); - TypeMention.Create(Context, Stmt.Declaration!.Type, this, type); + Expression.Create(Context, Stmt.Declaration!.Type, this, 0); } else // A catch clause of the form 'catch { ... }' { diff --git a/csharp/ql/lib/semmle/code/csharp/Stmt.qll b/csharp/ql/lib/semmle/code/csharp/Stmt.qll index 4d79bf9fa54..3be818e43a5 100644 --- a/csharp/ql/lib/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/lib/semmle/code/csharp/Stmt.qll @@ -995,6 +995,23 @@ class SpecificCatchClause extends CatchClause { /** Gets the local variable declaration of this catch clause, if any. */ LocalVariableDeclExpr getVariableDeclExpr() { result.getParent() = this } + /** + * Gets the type access of this catch clause, if it has no variable declaration. + * + * For example, the type access in + * + * ```csharp + * try { ... } + * catch (IOException) { ... } + * ``` + * + * is `IOException`. + */ + TypeAccess getTypeAccess() { + not exists(this.getVariableDeclExpr()) and + result = this.getChild(0) + } + override string toString() { result = "catch (...) {...}" } override string getAPrimaryQlClass() { result = "SpecificCatchClause" } 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 072f611a45a..12ee98812dc 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraph.qll @@ -90,6 +90,7 @@ module Ast implements AstSig { private AstNode getStmtChild0(Stmt s, int i) { not s instanceof FixedStmt and not s instanceof UsingBlockStmt and + not skipControlFlow(result) and result = s.getChild(i) or s = diff --git a/csharp/ql/src/change-notes/2026-06-23-catch-type-access.md b/csharp/ql/src/change-notes/2026-06-23-catch-type-access.md new file mode 100644 index 00000000000..b100178c171 --- /dev/null +++ b/csharp/ql/src/change-notes/2026-06-23-catch-type-access.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The C# extractor now extracts the exception type in a `catch(ExceptionType)` clause (without a variable) as a `TypeAccess` expression instead of a `TypeMention`. The new `SpecificCatchClause.getTypeAccess()` predicate provides access to this expression. diff --git a/csharp/ql/test/library-tests/csharp6/PrintAst.expected b/csharp/ql/test/library-tests/csharp6/PrintAst.expected index 140a63c941c..7471277e1ce 100644 --- a/csharp/ql/test/library-tests/csharp6/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp6/PrintAst.expected @@ -101,7 +101,8 @@ csharp6.cs: # 32| 0: [IntLiteral] 2 # 32| 0: [IntLiteral] 1 # 34| 1: [SpecificCatchClause] catch (...) {...} -# 34| 0: [TypeMention] IndexOutOfRangeException +# 34| 0: [TypeAccess] access to type IndexOutOfRangeException +# 34| 0: [TypeMention] IndexOutOfRangeException # 35| 1: [BlockStmt] {...} # 34| 2: [EQExpr] ... == ... # 34| 0: [PropertyCall] access to property Value diff --git a/csharp/ql/test/library-tests/statements/Checked1.expected b/csharp/ql/test/library-tests/statements/Checked1.expected index 2ddf5b6bcb7..a7c244a71fe 100644 --- a/csharp/ql/test/library-tests/statements/Checked1.expected +++ b/csharp/ql/test/library-tests/statements/Checked1.expected @@ -1 +1 @@ -| statements.cs:234:13:237:13 | checked {...} | statements.cs:235:13:237:13 | {...} | +| statements.cs:250:13:253:13 | checked {...} | statements.cs:251:13:253:13 | {...} | diff --git a/csharp/ql/test/library-tests/statements/CompilerGenerated.expected b/csharp/ql/test/library-tests/statements/CompilerGenerated.expected index 2c6994de712..ca3d54252e6 100644 --- a/csharp/ql/test/library-tests/statements/CompilerGenerated.expected +++ b/csharp/ql/test/library-tests/statements/CompilerGenerated.expected @@ -1,3 +1,3 @@ | fixed.cs:3:7:3:11 | {...} | fixed.cs:3:7:3:11 | Fixed | | statements.cs:8:11:8:15 | {...} | statements.cs:8:11:8:15 | Class | -| statements.cs:244:15:244:25 | {...} | statements.cs:244:15:244:25 | AccountLock | +| statements.cs:260:15:260:25 | {...} | statements.cs:260:15:260:25 | AccountLock | diff --git a/csharp/ql/test/library-tests/statements/Labeled1.expected b/csharp/ql/test/library-tests/statements/Labeled1.expected index a340cabc99f..86566ffa821 100644 --- a/csharp/ql/test/library-tests/statements/Labeled1.expected +++ b/csharp/ql/test/library-tests/statements/Labeled1.expected @@ -1 +1 @@ -| statements.cs:273:21:273:31 | MainLabeled | statements.cs:276:9:276:13 | Label: | +| statements.cs:289:21:289:31 | MainLabeled | statements.cs:292:9:292:13 | Label: | diff --git a/csharp/ql/test/library-tests/statements/Lock2.expected b/csharp/ql/test/library-tests/statements/Lock2.expected index aa76edc6a71..bcf3662f1df 100644 --- a/csharp/ql/test/library-tests/statements/Lock2.expected +++ b/csharp/ql/test/library-tests/statements/Lock2.expected @@ -1 +1 @@ -| statements.cs:249:17:256:17 | lock (...) {...} | statements.cs:249:23:249:26 | this access | statements.cs:250:17:256:17 | {...} | +| statements.cs:265:17:272:17 | lock (...) {...} | statements.cs:265:23:265:26 | this access | statements.cs:266:17:272:17 | {...} | diff --git a/csharp/ql/test/library-tests/statements/Lock3.expected b/csharp/ql/test/library-tests/statements/Lock3.expected index a9eded76979..25f3302c5e1 100644 --- a/csharp/ql/test/library-tests/statements/Lock3.expected +++ b/csharp/ql/test/library-tests/statements/Lock3.expected @@ -1 +1 @@ -| statements.cs:285:13:288:13 | lock (...) {...} | statements.cs:285:19:285:28 | access to field lockObject | Lock | statements.cs:286:13:288:13 | {...} | +| statements.cs:301:13:304:13 | lock (...) {...} | statements.cs:301:19:301:28 | access to field lockObject | Lock | statements.cs:302:13:304:13 | {...} | diff --git a/csharp/ql/test/library-tests/statements/PrintAst.expected b/csharp/ql/test/library-tests/statements/PrintAst.expected index 59af8ce4a2e..a37d3d0bbd6 100644 --- a/csharp/ql/test/library-tests/statements/PrintAst.expected +++ b/csharp/ql/test/library-tests/statements/PrintAst.expected @@ -603,115 +603,147 @@ statements.cs: # 223| -1: [TypeAccess] access to type Console # 223| 0: [TypeMention] Console # 223| 0: [StringLiteralUtf16] "Exception" -# 231| 27: [Method] MainCheckedUnchecked +# 231| 27: [Method] MainTryCatchNoVar # 231| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 231| 0: [Parameter] args +# 231| -1: [TypeMention] String[] +# 231| 1: [TypeMention] string # 232| 4: [BlockStmt] {...} -# 233| 0: [LocalVariableDeclStmt] ... ...; -# 233| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... -# 233| -1: [TypeMention] int -# 233| 0: [LocalVariableAccess] access to local variable i -# 233| 1: [MemberConstantAccess] access to constant MaxValue -# 233| -1: [TypeAccess] access to type Int32 -# 233| 0: [TypeMention] int -# 234| 1: [CheckedStmt] checked {...} -# 235| 0: [BlockStmt] {...} -# 236| 0: [ExprStmt] ...; -# 236| 0: [MethodCall] call to method WriteLine -# 236| -1: [TypeAccess] access to type Console -# 236| 0: [TypeMention] Console -# 236| 0: [AddExpr] ... + ... -# 236| 0: [LocalVariableAccess] access to local variable i -# 236| 1: [IntLiteral] 1 -# 238| 2: [UncheckedStmt] unchecked {...} -# 239| 0: [BlockStmt] {...} -# 240| 0: [ExprStmt] ...; -# 240| 0: [MethodCall] call to method WriteLine -# 240| -1: [TypeAccess] access to type Console -# 240| 0: [TypeMention] Console -# 240| 0: [AddExpr] ... + ... -# 240| 0: [LocalVariableAccess] access to local variable i -# 240| 1: [IntLiteral] 1 -# 244| 28: [Class] AccountLock -# 246| 6: [Field] balance -# 246| -1: [TypeMention] decimal -# 247| 7: [Method] Withdraw -# 247| -1: [TypeMention] Void +# 233| 0: [TryStmt] try {...} ... +# 234| 0: [BlockStmt] {...} +# 235| 0: [ExprStmt] ...; +# 235| 0: [MethodCall] call to method WriteLine +# 235| -1: [TypeAccess] access to type Console +# 235| 0: [TypeMention] Console +# 235| 0: [StringLiteralUtf16] "try" +# 237| 1: [SpecificCatchClause] catch (...) {...} +# 237| 0: [TypeAccess] access to type IOException +# 237| 0: [TypeMention] IOException +# 238| 1: [BlockStmt] {...} +# 239| 0: [ExprStmt] ...; +# 239| 0: [MethodCall] call to method WriteLine +# 239| -1: [TypeAccess] access to type Console +# 239| 0: [TypeMention] Console +# 239| 0: [StringLiteralUtf16] "catch (IOException) without variable" +# 241| 2: [SpecificCatchClause] catch (...) {...} +# 241| 0: [TypeAccess] access to type Exception +# 241| 0: [TypeMention] Exception +# 242| 1: [BlockStmt] {...} +# 243| 0: [ExprStmt] ...; +# 243| 0: [MethodCall] call to method WriteLine +# 243| -1: [TypeAccess] access to type Console +# 243| 0: [TypeMention] Console +# 243| 0: [StringLiteralUtf16] "catch (Exception) without variable" +# 247| 28: [Method] MainCheckedUnchecked +# 247| -1: [TypeMention] Void +# 248| 4: [BlockStmt] {...} +# 249| 0: [LocalVariableDeclStmt] ... ...; +# 249| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 249| -1: [TypeMention] int +# 249| 0: [LocalVariableAccess] access to local variable i +# 249| 1: [MemberConstantAccess] access to constant MaxValue +# 249| -1: [TypeAccess] access to type Int32 +# 249| 0: [TypeMention] int +# 250| 1: [CheckedStmt] checked {...} +# 251| 0: [BlockStmt] {...} +# 252| 0: [ExprStmt] ...; +# 252| 0: [MethodCall] call to method WriteLine +# 252| -1: [TypeAccess] access to type Console +# 252| 0: [TypeMention] Console +# 252| 0: [AddExpr] ... + ... +# 252| 0: [LocalVariableAccess] access to local variable i +# 252| 1: [IntLiteral] 1 +# 254| 2: [UncheckedStmt] unchecked {...} +# 255| 0: [BlockStmt] {...} +# 256| 0: [ExprStmt] ...; +# 256| 0: [MethodCall] call to method WriteLine +# 256| -1: [TypeAccess] access to type Console +# 256| 0: [TypeMention] Console +# 256| 0: [AddExpr] ... + ... +# 256| 0: [LocalVariableAccess] access to local variable i +# 256| 1: [IntLiteral] 1 +# 260| 29: [Class] AccountLock +# 262| 6: [Field] balance +# 262| -1: [TypeMention] decimal +# 263| 7: [Method] Withdraw +# 263| -1: [TypeMention] Void #-----| 2: (Parameters) -# 247| 0: [Parameter] amount -# 247| -1: [TypeMention] decimal -# 248| 4: [BlockStmt] {...} -# 249| 0: [LockStmt] lock (...) {...} -# 249| 0: [ThisAccess] this access -# 250| 1: [BlockStmt] {...} -# 251| 0: [IfStmt] if (...) ... -# 251| 0: [GTExpr] ... > ... -# 251| 0: [ParameterAccess] access to parameter amount -# 251| 1: [FieldAccess] access to field balance -# 252| 1: [BlockStmt] {...} -# 253| 0: [ThrowStmt] throw ...; -# 253| 0: [ObjectCreation] object creation of type Exception -# 253| -1: [TypeMention] Exception -# 253| 0: [StringLiteralUtf16] "Insufficient funds" -# 255| 1: [ExprStmt] ...; -# 255| 0: [AssignSubExpr] ... -= ... -# 255| 0: [FieldAccess] access to field balance -# 255| 1: [ParameterAccess] access to parameter amount -# 260| 29: [Method] MainUsing -# 260| -1: [TypeMention] Void -# 261| 4: [BlockStmt] {...} -# 262| 0: [UsingBlockStmt] using (...) {...} -# 262| -1: [LocalVariableDeclAndInitExpr] TextWriter w = ... -# 262| -1: [TypeMention] TextWriter -# 262| 0: [LocalVariableAccess] access to local variable w -# 262| 1: [MethodCall] call to method CreateText -# 262| -1: [TypeAccess] access to type File -# 262| 0: [TypeMention] File -# 262| 0: [StringLiteralUtf16] "test.txt" -# 263| 1: [BlockStmt] {...} -# 264| 0: [ExprStmt] ...; -# 264| 0: [MethodCall] call to method WriteLine -# 264| -1: [LocalVariableAccess] access to local variable w -# 264| 0: [StringLiteralUtf16] "Line one" -# 265| 1: [ExprStmt] ...; -# 265| 0: [MethodCall] call to method WriteLine -# 265| -1: [LocalVariableAccess] access to local variable w -# 265| 0: [StringLiteralUtf16] "Line two" -# 266| 2: [ExprStmt] ...; -# 266| 0: [MethodCall] call to method WriteLine -# 266| -1: [LocalVariableAccess] access to local variable w -# 266| 0: [StringLiteralUtf16] "Line three" -# 268| 1: [UsingBlockStmt] using (...) {...} -# 268| 0: [MethodCall] call to method CreateText -# 268| -1: [TypeAccess] access to type File -# 268| 0: [TypeMention] File -# 268| 0: [StringLiteralUtf16] "test.txt" -# 269| 1: [BlockStmt] {...} -# 273| 30: [Method] MainLabeled -# 273| -1: [TypeMention] Void -# 274| 4: [BlockStmt] {...} -# 275| 0: [GotoLabelStmt] goto ...; -# 276| 1: [LabelStmt] Label: -# 277| 2: [LocalVariableDeclStmt] ... ...; -# 277| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... -# 277| -1: [TypeMention] int -# 277| 0: [LocalVariableAccess] access to local variable x -# 277| 1: [IntLiteral] 23 -# 278| 3: [ExprStmt] ...; -# 278| 0: [AssignExpr] ... = ... -# 278| 0: [LocalVariableAccess] access to local variable x -# 278| 1: [IntLiteral] 9 -# 281| 31: [Field] lockObject -# 281| -1: [TypeMention] Lock -# 281| 1: [ObjectCreation] object creation of type Lock -# 281| 0: [TypeMention] Lock -# 283| 32: [Method] LockMethod -# 283| -1: [TypeMention] Void -# 284| 4: [BlockStmt] {...} -# 285| 0: [LockStmt] lock (...) {...} -# 285| 0: [FieldAccess] access to field lockObject -# 286| 1: [BlockStmt] {...} -# 287| 0: [ExprStmt] ...; -# 287| 0: [MethodCall] call to method WriteLine -# 287| -1: [TypeAccess] access to type Console -# 287| 0: [TypeMention] Console -# 287| 0: [StringLiteralUtf16] "Locked" +# 263| 0: [Parameter] amount +# 263| -1: [TypeMention] decimal +# 264| 4: [BlockStmt] {...} +# 265| 0: [LockStmt] lock (...) {...} +# 265| 0: [ThisAccess] this access +# 266| 1: [BlockStmt] {...} +# 267| 0: [IfStmt] if (...) ... +# 267| 0: [GTExpr] ... > ... +# 267| 0: [ParameterAccess] access to parameter amount +# 267| 1: [FieldAccess] access to field balance +# 268| 1: [BlockStmt] {...} +# 269| 0: [ThrowStmt] throw ...; +# 269| 0: [ObjectCreation] object creation of type Exception +# 269| -1: [TypeMention] Exception +# 269| 0: [StringLiteralUtf16] "Insufficient funds" +# 271| 1: [ExprStmt] ...; +# 271| 0: [AssignSubExpr] ... -= ... +# 271| 0: [FieldAccess] access to field balance +# 271| 1: [ParameterAccess] access to parameter amount +# 276| 30: [Method] MainUsing +# 276| -1: [TypeMention] Void +# 277| 4: [BlockStmt] {...} +# 278| 0: [UsingBlockStmt] using (...) {...} +# 278| -1: [LocalVariableDeclAndInitExpr] TextWriter w = ... +# 278| -1: [TypeMention] TextWriter +# 278| 0: [LocalVariableAccess] access to local variable w +# 278| 1: [MethodCall] call to method CreateText +# 278| -1: [TypeAccess] access to type File +# 278| 0: [TypeMention] File +# 278| 0: [StringLiteralUtf16] "test.txt" +# 279| 1: [BlockStmt] {...} +# 280| 0: [ExprStmt] ...; +# 280| 0: [MethodCall] call to method WriteLine +# 280| -1: [LocalVariableAccess] access to local variable w +# 280| 0: [StringLiteralUtf16] "Line one" +# 281| 1: [ExprStmt] ...; +# 281| 0: [MethodCall] call to method WriteLine +# 281| -1: [LocalVariableAccess] access to local variable w +# 281| 0: [StringLiteralUtf16] "Line two" +# 282| 2: [ExprStmt] ...; +# 282| 0: [MethodCall] call to method WriteLine +# 282| -1: [LocalVariableAccess] access to local variable w +# 282| 0: [StringLiteralUtf16] "Line three" +# 284| 1: [UsingBlockStmt] using (...) {...} +# 284| 0: [MethodCall] call to method CreateText +# 284| -1: [TypeAccess] access to type File +# 284| 0: [TypeMention] File +# 284| 0: [StringLiteralUtf16] "test.txt" +# 285| 1: [BlockStmt] {...} +# 289| 31: [Method] MainLabeled +# 289| -1: [TypeMention] Void +# 290| 4: [BlockStmt] {...} +# 291| 0: [GotoLabelStmt] goto ...; +# 292| 1: [LabelStmt] Label: +# 293| 2: [LocalVariableDeclStmt] ... ...; +# 293| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 293| -1: [TypeMention] int +# 293| 0: [LocalVariableAccess] access to local variable x +# 293| 1: [IntLiteral] 23 +# 294| 3: [ExprStmt] ...; +# 294| 0: [AssignExpr] ... = ... +# 294| 0: [LocalVariableAccess] access to local variable x +# 294| 1: [IntLiteral] 9 +# 297| 32: [Field] lockObject +# 297| -1: [TypeMention] Lock +# 297| 1: [ObjectCreation] object creation of type Lock +# 297| 0: [TypeMention] Lock +# 299| 33: [Method] LockMethod +# 299| -1: [TypeMention] Void +# 300| 4: [BlockStmt] {...} +# 301| 0: [LockStmt] lock (...) {...} +# 301| 0: [FieldAccess] access to field lockObject +# 302| 1: [BlockStmt] {...} +# 303| 0: [ExprStmt] ...; +# 303| 0: [MethodCall] call to method WriteLine +# 303| -1: [TypeAccess] access to type Console +# 303| 0: [TypeMention] Console +# 303| 0: [StringLiteralUtf16] "Locked" diff --git a/csharp/ql/test/library-tests/statements/StripSingletonBlocks.expected b/csharp/ql/test/library-tests/statements/StripSingletonBlocks.expected index 3e4f80d91b2..3b87c28d243 100644 --- a/csharp/ql/test/library-tests/statements/StripSingletonBlocks.expected +++ b/csharp/ql/test/library-tests/statements/StripSingletonBlocks.expected @@ -17,9 +17,13 @@ | statements.cs:218:13:220:13 | {...} | statements.cs:219:17:219:45 | ...; | | statements.cs:222:13:224:13 | {...} | statements.cs:223:17:223:47 | ...; | | statements.cs:226:13:228:13 | {...} | statements.cs:227:17:227:47 | ...; | -| statements.cs:235:13:237:13 | {...} | statements.cs:236:17:236:41 | ...; | -| statements.cs:239:13:241:13 | {...} | statements.cs:240:17:240:41 | ...; | -| statements.cs:248:13:257:13 | {...} | statements.cs:249:17:256:17 | lock (...) {...} | -| statements.cs:252:21:254:21 | {...} | statements.cs:253:25:253:66 | throw ...; | -| statements.cs:284:9:289:9 | {...} | statements.cs:285:13:288:13 | lock (...) {...} | -| statements.cs:286:13:288:13 | {...} | statements.cs:287:17:287:44 | ...; | +| statements.cs:232:9:245:9 | {...} | statements.cs:233:13:244:13 | try {...} ... | +| statements.cs:234:13:236:13 | {...} | statements.cs:235:17:235:41 | ...; | +| statements.cs:238:13:240:13 | {...} | statements.cs:239:17:239:74 | ...; | +| statements.cs:242:13:244:13 | {...} | statements.cs:243:17:243:72 | ...; | +| statements.cs:251:13:253:13 | {...} | statements.cs:252:17:252:41 | ...; | +| statements.cs:255:13:257:13 | {...} | statements.cs:256:17:256:41 | ...; | +| statements.cs:264:13:273:13 | {...} | statements.cs:265:17:272:17 | lock (...) {...} | +| statements.cs:268:21:270:21 | {...} | statements.cs:269:25:269:66 | throw ...; | +| statements.cs:300:9:305:9 | {...} | statements.cs:301:13:304:13 | lock (...) {...} | +| statements.cs:302:13:304:13 | {...} | statements.cs:303:17:303:44 | ...; | diff --git a/csharp/ql/test/library-tests/statements/Switch4.expected b/csharp/ql/test/library-tests/statements/Switch4.expected index bec962e22b5..2c7fd78e81a 100644 --- a/csharp/ql/test/library-tests/statements/Switch4.expected +++ b/csharp/ql/test/library-tests/statements/Switch4.expected @@ -1,2 +1,2 @@ -| statements.cs:246:21:246:27 | balance | -| statements.cs:281:31:281:40 | lockObject | +| statements.cs:262:21:262:27 | balance | +| statements.cs:297:31:297:40 | lockObject | diff --git a/csharp/ql/test/library-tests/statements/TryCatch9.expected b/csharp/ql/test/library-tests/statements/TryCatch9.expected new file mode 100644 index 00000000000..dca98557dd4 --- /dev/null +++ b/csharp/ql/test/library-tests/statements/TryCatch9.expected @@ -0,0 +1,2 @@ +| statements.cs:237:13:240:13 | catch (...) {...} | statements.cs:237:20:237:30 | access to type IOException | file:///home/runner/work/codeql/codeql/csharp/extractor-pack/tools/linux64/System.Private.CoreLib.dll:0:0:0:0 | IOException | +| statements.cs:241:13:244:13 | catch (...) {...} | statements.cs:241:20:241:28 | access to type Exception | file:///home/runner/work/codeql/codeql/csharp/extractor-pack/tools/linux64/System.Private.CoreLib.dll:0:0:0:0 | Exception | diff --git a/csharp/ql/test/library-tests/statements/TryCatch9.ql b/csharp/ql/test/library-tests/statements/TryCatch9.ql new file mode 100644 index 00000000000..4844a13c54c --- /dev/null +++ b/csharp/ql/test/library-tests/statements/TryCatch9.ql @@ -0,0 +1,13 @@ +/** + * @name Test for try catches without variable + */ + +import csharp + +from Method m, TryStmt s, SpecificCatchClause c, TypeAccess ta +where + s.getEnclosingCallable() = m and + m.getName() = "MainTryCatchNoVar" and + s.getACatchClause() = c and + c.getTypeAccess() = ta +select c, ta, ta.getTarget() diff --git a/csharp/ql/test/library-tests/statements/Unchecked1.expected b/csharp/ql/test/library-tests/statements/Unchecked1.expected index a966b32032a..70c62899866 100644 --- a/csharp/ql/test/library-tests/statements/Unchecked1.expected +++ b/csharp/ql/test/library-tests/statements/Unchecked1.expected @@ -1 +1 @@ -| statements.cs:238:13:241:13 | unchecked {...} | statements.cs:239:13:241:13 | {...} | +| statements.cs:254:13:257:13 | unchecked {...} | statements.cs:255:13:257:13 | {...} | diff --git a/csharp/ql/test/library-tests/statements/Using2.expected b/csharp/ql/test/library-tests/statements/Using2.expected index 00ae3b0dffc..49856cf6a36 100644 --- a/csharp/ql/test/library-tests/statements/Using2.expected +++ b/csharp/ql/test/library-tests/statements/Using2.expected @@ -1 +1 @@ -| statements.cs:260:21:260:29 | MainUsing | +| statements.cs:276:21:276:29 | MainUsing | diff --git a/csharp/ql/test/library-tests/statements/Using3.expected b/csharp/ql/test/library-tests/statements/Using3.expected index 9ffab1eed42..897a26d8851 100644 --- a/csharp/ql/test/library-tests/statements/Using3.expected +++ b/csharp/ql/test/library-tests/statements/Using3.expected @@ -1 +1 @@ -| statements.cs:260:21:260:29 | MainUsing | statements.cs:262:31:262:31 | w | +| statements.cs:276:21:276:29 | MainUsing | statements.cs:278:31:278:31 | w | diff --git a/csharp/ql/test/library-tests/statements/statements.cs b/csharp/ql/test/library-tests/statements/statements.cs index e034404a00f..1b60e7c0939 100644 --- a/csharp/ql/test/library-tests/statements/statements.cs +++ b/csharp/ql/test/library-tests/statements/statements.cs @@ -228,6 +228,22 @@ namespace Statements } } + static void MainTryCatchNoVar(string[] args) + { + try + { + Console.WriteLine("try"); + } + catch (IOException) + { + Console.WriteLine("catch (IOException) without variable"); + } + catch (Exception) + { + Console.WriteLine("catch (Exception) without variable"); + } + } + static void MainCheckedUnchecked() { int i = int.MaxValue;