Skip to content

Commit aa60442

Browse files
authored
Merge pull request #20305 from hvitved/csharp/dataflow-base-non-exact-type
C#: Fix context-sensitive dispatch when using `base` qualifier
2 parents b361b0f + 611eca4 commit aa60442

File tree

4 files changed

+59
-4
lines changed

4 files changed

+59
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* A bug has been fixed in the data flow analysis, which means that flow through calls using the `base` qualifier may now be tracked more accurately.

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,14 @@ private module Internal {
270270
hasOverrider(t, c)
271271
}
272272

273+
/**
274+
* For `base` expressions, the extractor provides the type of the base
275+
* class instead of the derived class; this predicate provides the latter.
276+
*/
277+
private Type getBaseAdjustedType(BaseAccess base) {
278+
result = base.getEnclosingCallable().getDeclaringType()
279+
}
280+
273281
abstract private class DispatchOverridableCall extends DispatchCallImpl {
274282
pragma[noinline]
275283
OverridableCallable getAStaticTargetExt() {
@@ -360,7 +368,12 @@ private module Internal {
360368
private predicate contextArgHasType(DispatchCall ctx, Type t, boolean isExact) {
361369
exists(Expr arg, int i |
362370
this.relevantContext(ctx, i) and
363-
t = getAPossibleType(arg, isExact)
371+
(
372+
t = getBaseAdjustedType(arg) and isExact = false
373+
or
374+
not exists(getBaseAdjustedType(arg)) and
375+
t = getAPossibleType(arg, isExact)
376+
)
364377
|
365378
ctx.getArgument(i) = arg
366379
or
@@ -725,9 +738,7 @@ private module Internal {
725738

726739
Type getType(boolean isExact) {
727740
result = this.getType() and
728-
if
729-
this instanceof ObjectCreation or
730-
this instanceof BaseAccess
741+
if this instanceof ObjectCreation or this instanceof BaseAccess
731742
then isExact = true
732743
else isExact = false
733744
}

csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,33 @@ public interface InterfaceB
233233
{
234234
void Foo(A2 a, object o, bool cond);
235235
}
236+
237+
public class A3
238+
{
239+
public virtual void M1(object o)
240+
{
241+
this.M2(o);
242+
}
243+
244+
public virtual void M2(object o)
245+
{
246+
Sink(o); // should not have flow
247+
}
248+
249+
public static void Sink(object o)
250+
{
251+
}
252+
}
253+
254+
public class A4 : A3
255+
{
256+
public override void M2(object o)
257+
{
258+
Sink(o); // should have flow
259+
}
260+
261+
private void CallM1()
262+
{
263+
base.M1(new object());
264+
}
265+
}

csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ edges
5959
| CallSensitivityFlow.cs:187:13:187:13 | access to local variable o : Object | CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | provenance | |
6060
| CallSensitivityFlow.cs:187:17:187:30 | call to method CallMOut : Object | CallSensitivityFlow.cs:187:13:187:13 | access to local variable o : Object | provenance | |
6161
| CallSensitivityFlow.cs:205:40:205:40 | o : Object | CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | provenance | |
62+
| CallSensitivityFlow.cs:239:35:239:35 | o : Object | CallSensitivityFlow.cs:241:17:241:17 | access to parameter o : Object | provenance | |
63+
| CallSensitivityFlow.cs:241:17:241:17 | access to parameter o : Object | CallSensitivityFlow.cs:256:36:256:36 | o : Object | provenance | |
64+
| CallSensitivityFlow.cs:256:36:256:36 | o : Object | CallSensitivityFlow.cs:258:14:258:14 | access to parameter o | provenance | |
65+
| CallSensitivityFlow.cs:263:17:263:28 | object creation of type Object : Object | CallSensitivityFlow.cs:239:35:239:35 | o : Object | provenance | |
6266
nodes
6367
| CallSensitivityFlow.cs:7:38:7:38 | o : Object | semmle.label | o : Object |
6468
| CallSensitivityFlow.cs:11:20:11:20 | access to parameter o : Object | semmle.label | access to parameter o : Object |
@@ -132,6 +136,11 @@ nodes
132136
| CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | semmle.label | access to local variable o |
133137
| CallSensitivityFlow.cs:205:40:205:40 | o : Object | semmle.label | o : Object |
134138
| CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | semmle.label | access to parameter o |
139+
| CallSensitivityFlow.cs:239:35:239:35 | o : Object | semmle.label | o : Object |
140+
| CallSensitivityFlow.cs:241:17:241:17 | access to parameter o : Object | semmle.label | access to parameter o : Object |
141+
| CallSensitivityFlow.cs:256:36:256:36 | o : Object | semmle.label | o : Object |
142+
| CallSensitivityFlow.cs:258:14:258:14 | access to parameter o | semmle.label | access to parameter o |
143+
| CallSensitivityFlow.cs:263:17:263:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
135144
subpaths
136145
| CallSensitivityFlow.cs:85:26:85:37 | object creation of type Object : Object | CallSensitivityFlow.cs:7:38:7:38 | o : Object | CallSensitivityFlow.cs:11:20:11:20 | access to parameter o : Object | CallSensitivityFlow.cs:85:14:85:44 | call to method FlowThrough |
137146
| CallSensitivityFlow.cs:105:26:105:37 | object creation of type Object : Object | CallSensitivityFlow.cs:7:38:7:38 | o : Object | CallSensitivityFlow.cs:11:20:11:20 | access to parameter o : Object | CallSensitivityFlow.cs:105:14:105:41 | call to method FlowThrough |
@@ -156,3 +165,4 @@ subpaths
156165
| CallSensitivityFlow.cs:172:37:172:48 | object creation of type Object : Object | CallSensitivityFlow.cs:172:37:172:48 | object creation of type Object : Object | CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | $@ | CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | access to local variable o |
157166
| CallSensitivityFlow.cs:182:21:182:32 | object creation of type Object : Object | CallSensitivityFlow.cs:182:21:182:32 | object creation of type Object : Object | CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | $@ | CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | access to parameter o |
158167
| CallSensitivityFlow.cs:185:21:185:32 | object creation of type Object : Object | CallSensitivityFlow.cs:185:21:185:32 | object creation of type Object : Object | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | $@ | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | access to parameter o |
168+
| CallSensitivityFlow.cs:263:17:263:28 | object creation of type Object : Object | CallSensitivityFlow.cs:263:17:263:28 | object creation of type Object : Object | CallSensitivityFlow.cs:258:14:258:14 | access to parameter o | $@ | CallSensitivityFlow.cs:258:14:258:14 | access to parameter o | access to parameter o |

0 commit comments

Comments
 (0)