mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #5052 from tamasvajk/feature/fnptr-df
C#: Add data flow 'getARuntimeTarget' predicate to 'FunctionPointerCall'
This commit is contained in:
@@ -63,7 +63,7 @@ predicate mayEscape(LocalVariable v) {
|
||||
exists(Callable c, Expr e, Expr succ | c = getACapturingCallableAncestor(v) |
|
||||
e = getADelegateExpr(c) and
|
||||
DataFlow::localExprFlow(e, succ) and
|
||||
not succ = any(DelegateCall dc).getDelegateExpr() and
|
||||
not succ = any(DelegateCall dc).getExpr() and
|
||||
not succ = any(Cast cast).getExpr() and
|
||||
not succ = any(Call call | nonEscapingCall(call)).getAnArgument() and
|
||||
not succ = any(AssignableDefinition ad | ad.getTarget() instanceof LocalVariable).getSource()
|
||||
|
||||
@@ -97,9 +97,7 @@ private class TranslatedDelegateInvokeCall extends TranslatedCompilerGeneratedCa
|
||||
)
|
||||
}
|
||||
|
||||
override TranslatedExprBase getQualifier() {
|
||||
result = getTranslatedExpr(generatedBy.getDelegateExpr())
|
||||
}
|
||||
override TranslatedExprBase getQualifier() { result = getTranslatedExpr(generatedBy.getExpr()) }
|
||||
|
||||
override Instruction getQualifierResult() { result = getQualifier().getResult() }
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ cached
|
||||
private newtype TCallContext =
|
||||
TEmptyCallContext() or
|
||||
TArgNonDelegateCallContext(Expr arg) { exists(DispatchCall dc | arg = dc.getArgument(_)) } or
|
||||
TArgDelegateCallContext(DelegateCall dc, int i) { exists(dc.getArgument(i)) }
|
||||
TArgDelegateCallContext(DelegateCall dc, int i) { exists(dc.getArgument(i)) } or
|
||||
TArgFunctionPointerCallContext(FunctionPointerCall fptrc, int i) { exists(fptrc.getArgument(i)) }
|
||||
|
||||
/**
|
||||
* A call context.
|
||||
@@ -60,12 +61,14 @@ class NonDelegateCallArgumentCallContext extends ArgumentCallContext, TArgNonDel
|
||||
override Location getLocation() { result = arg.getLocation() }
|
||||
}
|
||||
|
||||
/** An argument of a delegate call. */
|
||||
class DelegateCallArgumentCallContext extends ArgumentCallContext, TArgDelegateCallContext {
|
||||
DelegateCall dc;
|
||||
/** An argument of a delegate or function pointer call. */
|
||||
class DelegateLikeCallArgumentCallContext extends ArgumentCallContext {
|
||||
DelegateLikeCall dc;
|
||||
int arg;
|
||||
|
||||
DelegateCallArgumentCallContext() { this = TArgDelegateCallContext(dc, arg) }
|
||||
DelegateLikeCallArgumentCallContext() {
|
||||
this = TArgDelegateCallContext(dc, arg) or this = TArgFunctionPointerCallContext(dc, arg)
|
||||
}
|
||||
|
||||
override predicate isArgument(Expr call, int i) {
|
||||
call = dc and
|
||||
@@ -76,3 +79,11 @@ class DelegateCallArgumentCallContext extends ArgumentCallContext, TArgDelegateC
|
||||
|
||||
override Location getLocation() { result = dc.getArgument(arg).getLocation() }
|
||||
}
|
||||
|
||||
/** An argument of a delegate call. */
|
||||
class DelegateCallArgumentCallContext extends DelegateLikeCallArgumentCallContext,
|
||||
TArgDelegateCallContext { }
|
||||
|
||||
/** An argument of a function pointer call. */
|
||||
class FunctionPointerCallArgumentCallContext extends DelegateLikeCallArgumentCallContext,
|
||||
TArgFunctionPointerCallContext { }
|
||||
|
||||
@@ -101,7 +101,7 @@ private module Cached {
|
||||
TNonDelegateCall(ControlFlow::Nodes::ElementNode cfn, DispatchCall dc) {
|
||||
cfn.getElement() = dc.getCall()
|
||||
} or
|
||||
TExplicitDelegateCall(ControlFlow::Nodes::ElementNode cfn, DelegateCall dc) {
|
||||
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
|
||||
cfn.getElement() = dc
|
||||
} or
|
||||
TTransitiveCapturedCall(ControlFlow::Nodes::ElementNode cfn, Callable target) {
|
||||
@@ -308,12 +308,12 @@ abstract class DelegateDataFlowCall extends DataFlowCall {
|
||||
override DataFlowCallable getARuntimeTarget() { result = this.getARuntimeTarget(_) }
|
||||
}
|
||||
|
||||
/** An explicit delegate call relevant for data flow. */
|
||||
class ExplicitDelegateDataFlowCall extends DelegateDataFlowCall, TExplicitDelegateCall {
|
||||
/** An explicit delegate or function pointer call relevant for data flow. */
|
||||
class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDelegateLikeCall {
|
||||
private ControlFlow::Nodes::ElementNode cfn;
|
||||
private DelegateCall dc;
|
||||
private DelegateLikeCall dc;
|
||||
|
||||
ExplicitDelegateDataFlowCall() { this = TExplicitDelegateCall(cfn, dc) }
|
||||
ExplicitDelegateLikeDataFlowCall() { this = TExplicitDelegateLikeCall(cfn, dc) }
|
||||
|
||||
override DataFlowCallable getARuntimeTarget(CallContext::CallContext cc) {
|
||||
result = getCallableForDataFlow(dc.getARuntimeTarget(cc))
|
||||
|
||||
@@ -1394,7 +1394,7 @@ private module OutNodes {
|
||||
|
||||
private DataFlowCall csharpCall(Expr e, ControlFlow::Node cfn) {
|
||||
e = any(DispatchCall dc | result = TNonDelegateCall(cfn, dc)).getCall() or
|
||||
result = TExplicitDelegateCall(cfn, e)
|
||||
result = TExplicitDelegateLikeCall(cfn, e)
|
||||
}
|
||||
|
||||
/** A valid return type for a method that uses `yield return`. */
|
||||
|
||||
@@ -14,8 +14,14 @@ private import semmle.code.csharp.dataflow.FlowSummary
|
||||
private import semmle.code.csharp.dispatch.Dispatch
|
||||
private import semmle.code.csharp.frameworks.system.linq.Expressions
|
||||
|
||||
/** A source of flow for a delegate or function pointer expression. */
|
||||
abstract private class DelegateLikeFlowSource extends DataFlow::ExprNode {
|
||||
/** Gets the callable that is referenced in this delegate or function pointer flow source. */
|
||||
abstract Callable getCallable();
|
||||
}
|
||||
|
||||
/** A source of flow for a delegate expression. */
|
||||
private class DelegateFlowSource extends DataFlow::ExprNode {
|
||||
private class DelegateFlowSource extends DelegateLikeFlowSource {
|
||||
Callable c;
|
||||
|
||||
DelegateFlowSource() {
|
||||
@@ -27,11 +33,29 @@ private class DelegateFlowSource extends DataFlow::ExprNode {
|
||||
}
|
||||
|
||||
/** Gets the callable that is referenced in this delegate flow source. */
|
||||
Callable getCallable() { result = c }
|
||||
override Callable getCallable() { result = c }
|
||||
}
|
||||
|
||||
/** A sink of flow for a delegate expression. */
|
||||
abstract private class DelegateFlowSink extends DataFlow::Node {
|
||||
/** A source of flow for a function pointer expression. */
|
||||
private class FunctionPointerFlowSource extends DelegateLikeFlowSource {
|
||||
Callable c;
|
||||
|
||||
FunctionPointerFlowSource() {
|
||||
c =
|
||||
this.getExpr()
|
||||
.(AddressOfExpr)
|
||||
.getOperand()
|
||||
.(CallableAccess)
|
||||
.getTarget()
|
||||
.getUnboundDeclaration()
|
||||
}
|
||||
|
||||
/** Gets the callable that is referenced in this function pointer flow source. */
|
||||
override Callable getCallable() { result = c }
|
||||
}
|
||||
|
||||
/** A sink of flow for a delegate or function pointer expression. */
|
||||
abstract private class DelegateLikeFlowSink extends DataFlow::Node {
|
||||
/**
|
||||
* Gets an actual run-time target of this delegate call in the given call
|
||||
* context, if any. The call context records the *last* call required to
|
||||
@@ -85,25 +109,25 @@ abstract private class DelegateFlowSink extends DataFlow::Node {
|
||||
*/
|
||||
cached
|
||||
Callable getARuntimeTarget(CallContext context) {
|
||||
exists(DelegateFlowSource dfs |
|
||||
exists(DelegateLikeFlowSource dfs |
|
||||
flowsFrom(this, dfs, _, context) and
|
||||
result = dfs.getCallable()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A delegate call expression. */
|
||||
class DelegateCallExpr extends DelegateFlowSink, DataFlow::ExprNode {
|
||||
DelegateCall dc;
|
||||
/** A delegate or function pointer call expression. */
|
||||
class DelegateLikeCallExpr extends DelegateLikeFlowSink, DataFlow::ExprNode {
|
||||
DelegateLikeCall dc;
|
||||
|
||||
DelegateCallExpr() { this.getExpr() = dc.getDelegateExpr() }
|
||||
DelegateLikeCallExpr() { this.getExpr() = dc.getExpr() }
|
||||
|
||||
/** Gets the delegate call that this expression belongs to. */
|
||||
DelegateCall getDelegateCall() { result = dc }
|
||||
/** Gets the delegate or function pointer call that this expression belongs to. */
|
||||
DelegateLikeCall getCall() { result = dc }
|
||||
}
|
||||
|
||||
/** A parameter of delegate type belonging to a callable with a flow summary. */
|
||||
class SummaryDelegateParameterSink extends DelegateFlowSink, ParameterNode {
|
||||
class SummaryDelegateParameterSink extends DelegateLikeFlowSink, ParameterNode {
|
||||
SummaryDelegateParameterSink() {
|
||||
this.getType() instanceof SystemLinqExpressions::DelegateExtType and
|
||||
this.isParameterOf(any(SummarizedCallable c), _)
|
||||
@@ -111,7 +135,7 @@ class SummaryDelegateParameterSink extends DelegateFlowSink, ParameterNode {
|
||||
}
|
||||
|
||||
/** A delegate expression that is added to an event. */
|
||||
class AddEventSource extends DelegateFlowSink, DataFlow::ExprNode {
|
||||
class AddEventSource extends DelegateLikeFlowSink, DataFlow::ExprNode {
|
||||
AddEventExpr ae;
|
||||
|
||||
AddEventSource() { this.getExpr() = ae.getRValue() }
|
||||
@@ -150,7 +174,7 @@ private class NormalReturnNode extends Node {
|
||||
* records the last call on the path from `node` to `sink`, if any.
|
||||
*/
|
||||
private predicate flowsFrom(
|
||||
DelegateFlowSink sink, DataFlow::Node node, boolean isReturned, CallContext lastCall
|
||||
DelegateLikeFlowSink sink, DataFlow::Node node, boolean isReturned, CallContext lastCall
|
||||
) {
|
||||
// Base case
|
||||
sink = node and
|
||||
@@ -188,7 +212,8 @@ private predicate flowsFrom(
|
||||
or
|
||||
// Flow into a callable (delegate call)
|
||||
exists(
|
||||
ParameterNode mid, CallContext prevLastCall, DelegateCall call, Callable c, Parameter p, int i
|
||||
ParameterNode mid, CallContext prevLastCall, DelegateLikeCall call, Callable c, Parameter p,
|
||||
int i
|
||||
|
|
||||
flowsFrom(sink, mid, isReturned, prevLastCall) and
|
||||
isReturned = false and
|
||||
@@ -238,14 +263,14 @@ private predicate flowIntoNonDelegateCall(NonDelegateCall call, Expr arg, DotNet
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate flowIntoDelegateCall(DelegateCall call, Callable c, Expr arg, int i) {
|
||||
exists(DelegateFlowSource dfs, DelegateCallExpr dce |
|
||||
private predicate flowIntoDelegateCall(DelegateLikeCall call, Callable c, Expr arg, int i) {
|
||||
exists(DelegateLikeFlowSource dfs, DelegateLikeCallExpr dce |
|
||||
// the call context is irrelevant because the delegate call
|
||||
// itself will be the context
|
||||
flowsFrom(dce, dfs, _, _) and
|
||||
arg = call.getArgument(i) and
|
||||
c = dfs.getCallable() and
|
||||
call = dce.getDelegateCall()
|
||||
call = dce.getCall()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -255,11 +280,13 @@ private predicate flowOutOfNonDelegateCall(NonDelegateCall call, NormalReturnNod
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate flowOutOfDelegateCall(DelegateCall dc, NormalReturnNode ret, CallContext lastCall) {
|
||||
exists(DelegateFlowSource dfs, DelegateCallExpr dce, Callable c |
|
||||
private predicate flowOutOfDelegateCall(
|
||||
DelegateLikeCall dc, NormalReturnNode ret, CallContext lastCall
|
||||
) {
|
||||
exists(DelegateLikeFlowSource dfs, DelegateLikeCallExpr dce, Callable c |
|
||||
flowsFrom(dce, dfs, _, lastCall) and
|
||||
ret.getEnclosingCallable() = c and
|
||||
c = dfs.getCallable() and
|
||||
dc = dce.getDelegateCall()
|
||||
dc = dce.getCall()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ private module CallGraph {
|
||||
* a library callable and `e` is a delegate argument.
|
||||
*/
|
||||
private predicate delegateCall(Call c, Expr e, boolean libraryDelegateCall) {
|
||||
c = any(DelegateCall dc | e = dc.getDelegateExpr()) and
|
||||
c = any(DelegateCall dc | e = dc.getExpr()) and
|
||||
libraryDelegateCall = false
|
||||
or
|
||||
c.getTarget().fromLibrary() and
|
||||
|
||||
@@ -527,6 +527,46 @@ class MutatorOperatorCall extends OperatorCall {
|
||||
predicate isPostfix() { mutator_invocation_mode(this, 2) }
|
||||
}
|
||||
|
||||
private class DelegateLikeCall_ = @delegate_invocation_expr or @function_pointer_invocation_expr;
|
||||
|
||||
/**
|
||||
* A function pointer or delegate call.
|
||||
*/
|
||||
class DelegateLikeCall extends Call, DelegateLikeCall_ {
|
||||
override Callable getTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets a potential run-time target of this delegate or function pointer call in the given
|
||||
* call context `cc`.
|
||||
*/
|
||||
Callable getARuntimeTarget(CallContext::CallContext cc) {
|
||||
exists(DelegateLikeCallExpr call |
|
||||
this = call.getCall() and
|
||||
result = call.getARuntimeTarget(cc)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the delegate or function pointer expression of this call. For example, the
|
||||
* delegate expression of `X()` on line 5 is the access to the field `X` in
|
||||
*
|
||||
* ```csharp
|
||||
* class A {
|
||||
* Action X = () => { };
|
||||
*
|
||||
* void CallX() {
|
||||
* X();
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(-1) }
|
||||
|
||||
override Callable getARuntimeTarget() { result = getARuntimeTarget(_) }
|
||||
|
||||
override Expr getRuntimeArgument(int i) { result = getArgument(i) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegate call, for example `x()` on line 5 in
|
||||
*
|
||||
@@ -540,18 +580,13 @@ class MutatorOperatorCall extends OperatorCall {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class DelegateCall extends Call, @delegate_invocation_expr {
|
||||
override Callable getTarget() { none() }
|
||||
|
||||
class DelegateCall extends DelegateLikeCall, @delegate_invocation_expr {
|
||||
/**
|
||||
* Gets a potential run-time target of this delegate call in the given
|
||||
* call context `cc`.
|
||||
*/
|
||||
Callable getARuntimeTarget(CallContext::CallContext cc) {
|
||||
exists(DelegateCallExpr call |
|
||||
this = call.getDelegateCall() and
|
||||
result = call.getARuntimeTarget(cc)
|
||||
)
|
||||
override Callable getARuntimeTarget(CallContext::CallContext cc) {
|
||||
result = DelegateLikeCall.super.getARuntimeTarget(cc)
|
||||
or
|
||||
exists(AddEventSource aes, CallContext::CallContext cc2 |
|
||||
aes = this.getAnAddEventSource(_) and
|
||||
@@ -567,7 +602,7 @@ class DelegateCall extends Call, @delegate_invocation_expr {
|
||||
}
|
||||
|
||||
private AddEventSource getAnAddEventSource(Callable enclosingCallable) {
|
||||
this.getDelegateExpr().(EventAccess).getTarget() = result.getEvent() and
|
||||
this.getExpr().(EventAccess).getTarget() = result.getEvent() and
|
||||
enclosingCallable = result.getExpr().getEnclosingCallable()
|
||||
}
|
||||
|
||||
@@ -579,25 +614,12 @@ class DelegateCall extends Call, @delegate_invocation_expr {
|
||||
exists(Callable c | result = getAnAddEventSource(c) | c != this.getEnclosingCallable())
|
||||
}
|
||||
|
||||
override Callable getARuntimeTarget() { result = getARuntimeTarget(_) }
|
||||
|
||||
override Expr getRuntimeArgument(int i) { result = getArgument(i) }
|
||||
|
||||
/**
|
||||
* Gets the delegate expression of this delegate call. For example, the
|
||||
* delegate expression of `X()` on line 5 is the access to the field `X` in
|
||||
* DEPRECATED: use `getExpr` instead.
|
||||
*
|
||||
* ```csharp
|
||||
* class A {
|
||||
* Action X = () => { };
|
||||
*
|
||||
* void CallX() {
|
||||
* X();
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* Gets the delegate expression of this call.
|
||||
*/
|
||||
Expr getDelegateExpr() { result = this.getChild(-1) }
|
||||
deprecated Expr getDelegateExpr() { result = this.getExpr() }
|
||||
|
||||
override string toString() { result = "delegate call" }
|
||||
|
||||
@@ -615,11 +637,7 @@ class DelegateCall extends Call, @delegate_invocation_expr {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class FunctionPointerCall extends Call, @function_pointer_invocation_expr {
|
||||
override Callable getTarget() { none() }
|
||||
|
||||
override Expr getRuntimeArgument(int i) { result = getArgument(i) }
|
||||
|
||||
class FunctionPointerCall extends DelegateLikeCall, @function_pointer_invocation_expr {
|
||||
override string toString() { result = "function pointer call" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FunctionPointerCall" }
|
||||
|
||||
@@ -78,7 +78,7 @@ predicate depends(ValueOrRefType t, ValueOrRefType u) {
|
||||
or
|
||||
exists(DelegateCall dc, DelegateType dt |
|
||||
dc.getEnclosingCallable().getDeclaringType() = t and
|
||||
dc.getDelegateExpr().getType() = dt and
|
||||
dc.getExpr().getType() = dt and
|
||||
usesType(dt.getUnboundDeclaration(), u)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -4,11 +4,11 @@ class DelegateFlow
|
||||
{
|
||||
void M1(int i) { }
|
||||
|
||||
void M2(Action<int> a)
|
||||
static void M2(Action<int> a)
|
||||
{
|
||||
a(0);
|
||||
a = _ => { };
|
||||
a(0);
|
||||
a(1);
|
||||
}
|
||||
|
||||
void M3()
|
||||
@@ -108,4 +108,20 @@ class DelegateFlow
|
||||
}
|
||||
|
||||
public delegate void MyDelegate();
|
||||
|
||||
public unsafe void M16(delegate*<Action<int>, void> fnptr, Action<int> a)
|
||||
{
|
||||
fnptr(a);
|
||||
}
|
||||
|
||||
public unsafe void M17()
|
||||
{
|
||||
M16(&M2, (i) => { });
|
||||
}
|
||||
|
||||
public unsafe void M18()
|
||||
{
|
||||
delegate*<Action<int>, void> fnptr = &M2;
|
||||
fnptr((i) => { });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ delegateCall
|
||||
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:16:12:16:19 | (...) => ... | DelegateFlow.cs:16:12:16:19 | (...) => ... |
|
||||
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:27:12:27:19 | (...) => ... | DelegateFlow.cs:22:12:22:12 | access to parameter a |
|
||||
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:98:9:98:37 | LocalFunction | DelegateFlow.cs:99:12:99:24 | delegate creation of type Action<Int32> |
|
||||
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:119:18:119:27 | (...) => ... | DelegateFlow.cs:114:15:114:15 | access to parameter a |
|
||||
| DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:125:15:125:24 | (...) => ... | DelegateFlow.cs:125:15:125:24 | (...) => ... |
|
||||
| DelegateFlow.cs:11:9:11:12 | delegate call | DelegateFlow.cs:10:13:10:20 | (...) => ... | file://:0:0:0:0 | <empty> |
|
||||
| DelegateFlow.cs:33:9:33:13 | delegate call | DelegateFlow.cs:38:12:38:25 | (...) => ... | DelegateFlow.cs:38:12:38:25 | (...) => ... |
|
||||
| DelegateFlow.cs:38:19:38:22 | delegate call | DelegateFlow.cs:5:10:5:11 | M1 | DelegateFlow.cs:33:12:33:12 | access to parameter a |
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
|
||||
unsafe class FunctionPointerFlow
|
||||
{
|
||||
public static void Log1(int i) { }
|
||||
public static void Log2(int i) { }
|
||||
public static void Log3(int i) { }
|
||||
public static void Log4(int i) { }
|
||||
public static void Log5(int i) { }
|
||||
public static void Log6(int i) { }
|
||||
|
||||
public static void M2(delegate*<int, void> a)
|
||||
{
|
||||
a(1);
|
||||
a = &Log3;
|
||||
a(2);
|
||||
}
|
||||
|
||||
public void M3()
|
||||
{
|
||||
M2(&Log1);
|
||||
}
|
||||
|
||||
public static void M4(delegate*<int, void> a)
|
||||
{
|
||||
M2(a);
|
||||
}
|
||||
|
||||
public void M5()
|
||||
{
|
||||
M4(&Log2);
|
||||
}
|
||||
|
||||
public delegate*<int, void> M6()
|
||||
{
|
||||
return &Log4;
|
||||
}
|
||||
|
||||
public void M7()
|
||||
{
|
||||
M6()(0);
|
||||
}
|
||||
|
||||
public void M8()
|
||||
{
|
||||
static void LocalFunction(int i) { };
|
||||
M2(&LocalFunction);
|
||||
}
|
||||
|
||||
private static delegate*<int, void> field = &Log5;
|
||||
|
||||
public void M9()
|
||||
{
|
||||
field(1);
|
||||
}
|
||||
|
||||
public void M10(delegate*<delegate*<int, void>, void> aa, delegate*<int, void> a)
|
||||
{
|
||||
aa(a);
|
||||
}
|
||||
|
||||
public void M11()
|
||||
{
|
||||
M10(&M4, &Log6);
|
||||
}
|
||||
|
||||
public void M16(delegate*<Action<int>, void> aa, Action<int> a)
|
||||
{
|
||||
aa(a);
|
||||
}
|
||||
|
||||
public static void M17(Action<int> a)
|
||||
{
|
||||
a(0);
|
||||
a = _ => { };
|
||||
a(0);
|
||||
}
|
||||
|
||||
public void M18()
|
||||
{
|
||||
M16(&M17, (i) => { });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:5:24:5:27 | Log1 | FunctionPointerFlow.cs:21:12:21:16 | &... |
|
||||
| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:6:24:6:27 | Log2 | FunctionPointerFlow.cs:26:12:26:12 | access to parameter a |
|
||||
| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:10:24:10:27 | Log6 | FunctionPointerFlow.cs:26:12:26:12 | access to parameter a |
|
||||
| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:46:9:46:44 | LocalFunction | FunctionPointerFlow.cs:47:12:47:25 | &... |
|
||||
| FunctionPointerFlow.cs:16:9:16:12 | function pointer call | FunctionPointerFlow.cs:7:24:7:27 | Log3 | file://:0:0:0:0 | <empty> |
|
||||
| FunctionPointerFlow.cs:41:9:41:15 | function pointer call | FunctionPointerFlow.cs:8:24:8:27 | Log4 | file://:0:0:0:0 | <empty> |
|
||||
| FunctionPointerFlow.cs:54:9:54:16 | function pointer call | FunctionPointerFlow.cs:9:24:9:27 | Log5 | file://:0:0:0:0 | <empty> |
|
||||
| FunctionPointerFlow.cs:59:9:59:13 | function pointer call | FunctionPointerFlow.cs:24:24:24:25 | M4 | FunctionPointerFlow.cs:64:13:64:15 | &... |
|
||||
| FunctionPointerFlow.cs:69:9:69:13 | function pointer call | FunctionPointerFlow.cs:72:24:72:26 | M17 | FunctionPointerFlow.cs:81:13:81:16 | &... |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
|
||||
query predicate fptrCall(FunctionPointerCall fptrc, Callable c, CallContext::CallContext cc) {
|
||||
c = fptrc.getARuntimeTarget(cc)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ where
|
||||
m.hasName("MainDelegateAndMethodAccesses") and
|
||||
e.getEnclosingCallable() = m and
|
||||
e.getNumberOfArguments() = 1 and
|
||||
e.getDelegateExpr() = a and
|
||||
e.getExpr() = a and
|
||||
a.getTarget().hasName("cd1") and
|
||||
e.getArgument(0).getValue() = "-40"
|
||||
select m, e, a
|
||||
|
||||
@@ -9,7 +9,7 @@ where
|
||||
m.hasName("MainDelegateAndMethodAccesses") and
|
||||
e.getEnclosingCallable() = m and
|
||||
e.getNumberOfArguments() = 1 and
|
||||
e.getDelegateExpr() = a and
|
||||
e.getExpr() = a and
|
||||
a.getTarget().hasName("cd7") and
|
||||
e.getArgument(0).(AddExpr).getRightOperand().(LocalVariableAccess).getTarget().hasName("x")
|
||||
select m, e, a
|
||||
|
||||
@@ -8,7 +8,7 @@ from Method m, DelegateCall e, LocalVariableAccess a
|
||||
where
|
||||
m.hasName("MainDelegateAndMethodAccesses") and
|
||||
e.getEnclosingCallable() = m and
|
||||
e.getDelegateExpr() = a and
|
||||
e.getExpr() = a and
|
||||
a.getTarget().hasName("cd7") and
|
||||
a.getTarget().getType().(DelegateType).hasQualifiedName("Expressions.D")
|
||||
select m, e, a
|
||||
|
||||
@@ -11,7 +11,7 @@ where
|
||||
e.getTarget().getName() = "Click" and
|
||||
e.getTarget().getDeclaringType() = m.getDeclaringType() and
|
||||
d.getEnclosingCallable() = m and
|
||||
d.getDelegateExpr() = e and
|
||||
d.getExpr() = e and
|
||||
d.getArgument(0) instanceof ThisAccess and
|
||||
d.getArgument(1).(ParameterAccess).getTarget().hasName("e")
|
||||
select m, d, e
|
||||
|
||||
Reference in New Issue
Block a user