C# extractor: extract catch(Ex) type as TypeAccess instead of TypeMention

This commit is contained in:
copilot-swe-agent[bot]
2026-06-23 09:02:49 +00:00
committed by GitHub
parent f0576046b1
commit 5310accfba
19 changed files with 217 additions and 127 deletions

View File

@@ -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 { ... }'
{

View File

@@ -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" }

View File

@@ -90,6 +90,7 @@ module Ast implements AstSig<Location> {
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 =

View File

@@ -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.

View File

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

View File

@@ -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 | {...} |

View File

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

View File

@@ -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: |

View File

@@ -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 | {...} |

View File

@@ -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 | {...} |

View File

@@ -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"

View File

@@ -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 | ...; |

View File

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

View File

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

View File

@@ -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()

View File

@@ -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 | {...} |

View File

@@ -1 +1 @@
| statements.cs:260:21:260:29 | MainUsing |
| statements.cs:276:21:276:29 | MainUsing |

View File

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

View File

@@ -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;