Skip to content

Commit 8136deb

Browse files
committed
C#: Add dispatching logic for direct (method) accessor calls.
1 parent 7c3126f commit 8136deb

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ private module Internal {
8787
newtype TDispatchCall =
8888
TDispatchMethodCall(MethodCall mc) {
8989
not isReflectionCall(mc, _, _, _, _) and
90-
not mc.isLateBound()
90+
not mc.isLateBound() and
91+
not isExtensionAccossorCall(mc)
9192
} or
9293
TDispatchAccessorCall(AccessorCall ac) or
9394
TDispatchOperatorCall(OperatorCall oc) { not oc.isLateBound() } or
@@ -110,7 +111,8 @@ private module Internal {
110111
c instanceof ConstructorInitializer
111112
or
112113
c instanceof LocalFunctionCall
113-
}
114+
} or
115+
TDispatchExtensionAccessorCall(MethodCall mc) { isExtensionAccossorCall(mc) }
114116

115117
cached
116118
Expr getCall(DispatchCall dc) { result = dc.(DispatchCallImpl).getCall() }
@@ -142,6 +144,10 @@ private module Internal {
142144

143145
import Cached
144146

147+
private predicate isExtensionAccossorCall(MethodCall mc) {
148+
exists(ExtensionAccessor a | mc.getTargetAccessor() = a)
149+
}
150+
145151
/**
146152
* Holds if `mc` is a reflection call to a method named `name`, where
147153
* `object` is the object on which to invoke the method (`null` if a
@@ -819,6 +825,33 @@ private module Internal {
819825
override Method getAStaticTarget() { result = this.getCall().getTarget() }
820826
}
821827

828+
/**
829+
* A call to an extension accessor method.
830+
*/
831+
private class DispatchExtensionAccessorCall extends DispatchCallImpl,
832+
TDispatchExtensionAccessorCall
833+
{
834+
override MethodCall getCall() { this = TDispatchExtensionAccessorCall(result) }
835+
836+
private Expr getArgumentForParameter(Parameter p) {
837+
this.getCall().getTargetAccessor().getAParameter() = p and
838+
result = this.getCall().getArgument(p.getPosition())
839+
}
840+
841+
override Expr getArgument(int i) {
842+
exists(MethodCall call, Parameter p | call = this.getCall() |
843+
p = call.getTargetAccessor().getParameter(i) and
844+
result = this.getArgumentForParameter(p)
845+
)
846+
}
847+
848+
override Expr getQualifier() { result = this.getCall().getQualifier() }
849+
850+
override Accessor getAStaticTarget() { result = this.getCall().getTargetAccessor() }
851+
852+
override RuntimeCallable getADynamicTarget() { result = this.getAStaticTarget() }
853+
}
854+
822855
/**
823856
* An ordinary operator call.
824857
*

0 commit comments

Comments
 (0)