Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 183926d

Browse files
committed
C#: Add QL classes for function pointer type/invocation, tests
1 parent 8761233 commit 183926d

9 files changed

Lines changed: 186 additions & 5 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
lgtm,codescanning
2+
* Function pointer types (`FunctionPointerType`) and call to function pointers
3+
(`FunctionPointerCall`) are extracted.

csharp/ql/src/semmle/code/csharp/Type.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,31 @@ class DelegateType extends RefType, Parameterizable, @delegate_type {
797797
override string getAPrimaryQlClass() { result = "DelegateType" }
798798
}
799799

800+
/**
801+
* A function pointer type, for example
802+
*
803+
* ```csharp
804+
* delegate*<int, void>
805+
* ```
806+
*/
807+
class FunctionPointerType extends Type, Parameterizable, @function_pointer_type {
808+
/** Gets the return type of this function pointer. */
809+
Type getReturnType() { function_pointer_return_type(this, getTypeRef(result)) }
810+
811+
/** Gets the calling convention. */
812+
int getCallingConvention() { function_pointer_calling_conventions(this, result) }
813+
814+
/** Gets the unmanaged calling convention at index `i`. */
815+
Type getUnmanagedCallingConvention(int i) {
816+
has_unmanaged_calling_conventions(this, i, getTypeRef(result))
817+
}
818+
819+
/** Gets an unmanaged calling convention. */
820+
Type getAnUnmanagedCallingConvention() { result = getUnmanagedCallingConvention(_) }
821+
822+
override string getAPrimaryQlClass() { result = "FunctionPointerType" }
823+
}
824+
800825
/**
801826
* The `null` type. The type of the `null` literal.
802827
*/

csharp/ql/src/semmle/code/csharp/exprs/Call.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,27 @@ class DelegateCall extends Call, @delegate_invocation_expr {
604604
override string getAPrimaryQlClass() { result = "DelegateCall" }
605605
}
606606

607+
/**
608+
* A function pointer call, for example `fp(1)` on line 3 in
609+
*
610+
* ```csharp
611+
* class A {
612+
* void Call(delegate*<int, void> fp) {
613+
* fp(1);
614+
* }
615+
* }
616+
* ```
617+
*/
618+
class FunctionPointerCall extends Call, @function_pointer_invocation_expr {
619+
override Callable getTarget() { none() }
620+
621+
override Expr getRuntimeArgument(int i) { result = getArgument(i) }
622+
623+
override string toString() { result = "function pointer call" }
624+
625+
override string getAPrimaryQlClass() { result = "FunctionPointerCall" }
626+
}
627+
607628
/**
608629
* A call to an accessor. Either a property accessor call (`PropertyCall`),
609630
* an indexer accessor call (`IndexerCall`), or an event accessor call

csharp/ql/test/library-tests/csharp9/FunctionPointer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
#nullable enable
44

5-
public class Class1
5+
public class FnPointer
66
{
77
public unsafe static class Program
88
{
9-
static delegate*<int> pointer = &Main;
9+
static delegate*<int> pointer = &M0;
1010

11-
public static int Main()
11+
public static int M0()
1212
{
1313
return 0;
1414
}
@@ -19,7 +19,7 @@ static void M1(delegate*<ref int, out object?, int> f)
1919
int j = f(ref i, out object? o);
2020
}
2121

22-
static void M2<T>(delegate* unmanaged[Stdcall, SuppressGCTransition]<ref int, out object?, T, void> f) where T : new()
22+
static void M2<T>(delegate* unmanaged[Stdcall/*, StdcallSuppressGCTransition*/]<ref int, out object?, T, void> f) where T : new()
2323
{
2424
int i = 42;
2525
f(ref i, out object? o, new T());
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
type
2+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | Int32 | 0 |
3+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | Int32 | 0 |
4+
| file://:0:0:0:0 | delegate* default<Int32> | Int32 | 0 |
5+
| file://:0:0:0:0 | delegate* default<T,Int32> | Int32 | 0 |
6+
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | 2 |
7+
unmanagedCallingConvention
8+
parameter
9+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | Int32 |
10+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | Object |
11+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | Int32 |
12+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 0 | file://:0:0:0:0 | | Int32 |
13+
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 1 | file://:0:0:0:0 | `1 | Object |
14+
| file://:0:0:0:0 | delegate* default<T,Int32> | 0 | file://:0:0:0:0 | | T |
15+
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 0 | file://:0:0:0:0 | | Int32 |
16+
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 1 | file://:0:0:0:0 | `1 | Object |
17+
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 2 | file://:0:0:0:0 | `2 | T |
18+
invocation
19+
| FunctionPointer.cs:19:21:19:43 | function pointer call |
20+
| FunctionPointer.cs:25:13:25:44 | function pointer call |
21+
| FunctionPointer.cs:31:29:31:57 | function pointer call |
22+
| FunctionPointer.cs:36:21:36:30 | function pointer call |
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import csharp
2+
3+
query predicate type(FunctionPointerType fpt, string returnType, int callingConvention) {
4+
fpt.getReturnType().toString() = returnType and
5+
fpt.getCallingConvention() = callingConvention
6+
}
7+
8+
query predicate unmanagedCallingConvention(FunctionPointerType fpt, int i, string callingConvention) {
9+
fpt.getUnmanagedCallingConvention(i).toString() = callingConvention
10+
}
11+
12+
query predicate parameter(FunctionPointerType fpt, int i, Parameter p, string t) {
13+
fpt.getParameter(i) = p and p.getType().toString() = t
14+
}
15+
16+
query predicate invocation(FunctionPointerCall fpc) { any() }

csharp/ql/test/library-tests/csharp9/PrintAst.expected

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
FunctionPointer.cs:
2+
# 9| [MethodAccess] access to method M0
13
AnonymousObjectCreation.cs:
24
# 5| [Class] AnonObj
35
# 7| 5: [Field] l
@@ -103,6 +105,94 @@ Discard.cs:
103105
# 10| 4: [BlockStmt] {...}
104106
# 10| 0: [ReturnStmt] return ...;
105107
# 10| 0: [IntLiteral] 0
108+
FunctionPointer.cs:
109+
# 5| [Class] FnPointer
110+
# 7| 5: [Class] Program
111+
# 9| 5: [Field] pointer
112+
# 9| -1: [TypeMention] delegate* default<Int32>
113+
# 9| 1: [AssignExpr] ... = ...
114+
# 9| 0: [FieldAccess] access to field pointer
115+
# 11| 6: [Method] M0
116+
# 11| -1: [TypeMention] int
117+
# 12| 4: [BlockStmt] {...}
118+
# 13| 0: [ReturnStmt] return ...;
119+
# 13| 0: [IntLiteral] 0
120+
# 16| 7: [Method] M1
121+
# 16| -1: [TypeMention] Void
122+
#-----| 2: (Parameters)
123+
# 16| 0: [Parameter] f
124+
# 16| -1: [TypeMention] delegate* default<Int32 ref,Object out,Int32>
125+
# 17| 4: [BlockStmt] {...}
126+
# 18| 0: [LocalVariableDeclStmt] ... ...;
127+
# 18| 0: [LocalVariableDeclAndInitExpr] Int32 i = ...
128+
# 18| -1: [TypeMention] int
129+
# 18| 0: [LocalVariableAccess] access to local variable i
130+
# 18| 1: [IntLiteral] 42
131+
# 19| 1: [LocalVariableDeclStmt] ... ...;
132+
# 19| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
133+
# 19| -1: [TypeMention] int
134+
# 19| 0: [LocalVariableAccess] access to local variable j
135+
# 19| 1: [FunctionPointerCall] function pointer call
136+
# 19| -1: [ParameterAccess] access to parameter f
137+
# 19| 0: [LocalVariableAccess] access to local variable i
138+
# 19| 1: [LocalVariableAccess,LocalVariableDeclExpr] Object o
139+
# 22| 8: [Method] M2
140+
# 22| -1: [TypeMention] Void
141+
#-----| 1: (Type parameters)
142+
# 22| 0: [TypeParameter] T
143+
#-----| 2: (Parameters)
144+
# 22| 0: [Parameter] f
145+
# 22| -1: [TypeMention] delegate* stdcall<Int32 ref,Object out,T,Void>
146+
# 23| 4: [BlockStmt] {...}
147+
# 24| 0: [LocalVariableDeclStmt] ... ...;
148+
# 24| 0: [LocalVariableDeclAndInitExpr] Int32 i = ...
149+
# 24| -1: [TypeMention] int
150+
# 24| 0: [LocalVariableAccess] access to local variable i
151+
# 24| 1: [IntLiteral] 42
152+
# 25| 1: [ExprStmt] ...;
153+
# 25| 0: [FunctionPointerCall] function pointer call
154+
# 25| -1: [ParameterAccess] access to parameter f
155+
# 25| 0: [LocalVariableAccess] access to local variable i
156+
# 25| 1: [LocalVariableAccess,LocalVariableDeclExpr] Object o
157+
# 25| 2: [ObjectCreation] object creation of type T
158+
# 25| 0: [TypeMention] T
159+
# 28| 9: [Method] M3
160+
# 28| -1: [TypeMention] Void
161+
#-----| 2: (Parameters)
162+
# 28| 0: [Parameter] f
163+
# 28| -1: [TypeMention] delegate* default<Int32 ref,Object out,Int32 in,Int32 ref>
164+
# 29| 4: [BlockStmt] {...}
165+
# 30| 0: [LocalVariableDeclStmt] ... ...;
166+
# 30| 0: [LocalVariableDeclAndInitExpr] Int32 i = ...
167+
# 30| -1: [TypeMention] int
168+
# 30| 0: [LocalVariableAccess] access to local variable i
169+
# 30| 1: [IntLiteral] 42
170+
# 31| 1: [LocalVariableDeclStmt] ... ...;
171+
# 31| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
172+
# 31| -1: [TypeMention] null
173+
# 31| 0: [LocalVariableAccess] access to local variable j
174+
# 31| 1: [RefExpr] ref ...
175+
# 31| 0: [FunctionPointerCall] function pointer call
176+
# 31| -1: [ParameterAccess] access to parameter f
177+
# 31| 0: [LocalVariableAccess] access to local variable i
178+
# 31| 1: [LocalVariableAccess,LocalVariableDeclExpr] Object o
179+
# 31| 2: [LocalVariableAccess] access to local variable i
180+
# 34| 10: [Method] M4
181+
# 34| -1: [TypeMention] Void
182+
#-----| 1: (Type parameters)
183+
# 34| 0: [TypeParameter] T
184+
#-----| 2: (Parameters)
185+
# 34| 0: [Parameter] f
186+
# 34| -1: [TypeMention] delegate* default<T,Int32>
187+
# 35| 4: [BlockStmt] {...}
188+
# 36| 0: [LocalVariableDeclStmt] ... ...;
189+
# 36| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
190+
# 36| -1: [TypeMention] int
191+
# 36| 0: [LocalVariableAccess] access to local variable j
192+
# 36| 1: [FunctionPointerCall] function pointer call
193+
# 36| -1: [ParameterAccess] access to parameter f
194+
# 36| 0: [ObjectCreation] object creation of type T
195+
# 36| 0: [TypeMention] T
106196
InitOnlyProperty.cs:
107197
# 3| [NamespaceDeclaration] namespace ... { ... }
108198
# 5| 1: [Class] IsExternalInit
@@ -136,6 +226,8 @@ InitOnlyProperty.cs:
136226
# 18| [Class] Derived
137227
#-----| 3: (Base types)
138228
# 18| 0: [TypeMention] Base
229+
# 18| 0: [TypeMention] Base
230+
# 18| 0: [TypeMention] Base
139231
# 20| 5: [Property] Prop1
140232
# 20| -1: [TypeMention] int
141233
# 20| 3: [Getter] get_Prop1

csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ valueType
1010
| TypeParameterNullability.cs:19:29:19:29 | T |
1111
| TypeParameterNullability.cs:24:29:24:29 | T |
1212
valueOrRefType
13+
| FunctionPointer.cs:22:24:22:24 | T |
14+
| FunctionPointer.cs:34:24:34:24 | T |
1315
| TypeParameterNullability.cs:5:28:5:28 | T |
1416
| TypeParameterNullability.cs:9:28:9:28 | T |
1517
| TypeParameterNullability.cs:15:29:15:29 | T |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
description: Added '@function_pointer_type', '@function_pointer_invocation_expr' and related relations.
2-
compatibility: full
2+
compatibility: backwards

0 commit comments

Comments
 (0)