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/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