Skip to content

Commit 6a6644b

Browse files
hvitvedtamasvajk
authored andcommitted
C#: Adjust data-flow for with expressions
In `x with { Foo = bar }`, instead of having a single data-flow step `x => x with { Foo = bar }` we now have two steps: `x => { Foo = bar }` and `{ Foo = bar } => x with { Foo = bar }` Moreover, `clearsContent` now targets the object initializer instead of the whole `with` expression, which means that it will only apply to values carried over from the old object and not those explicitly stored into the new object.
1 parent dd9b1d5 commit 6a6644b

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,16 @@ module LocalFlow {
210210
scope = e2 and
211211
isSuccessor = true
212212
or
213-
e1 = e2.(WithExpr).getExpr() and
214-
scope = e2 and
215-
isSuccessor = true
213+
exists(WithExpr we |
214+
scope = we and
215+
isSuccessor = true
216+
|
217+
e1 = we.getExpr() and
218+
e2 = we.getInitializer()
219+
or
220+
e1 = we.getInitializer() and
221+
e2 = we
222+
)
216223
)
217224
}
218225

@@ -799,8 +806,6 @@ private module Cached {
799806
predicate clearsContent(Node n, Content c) {
800807
fieldOrPropertyStore(_, c, _, n.asExpr(), true)
801808
or
802-
fieldOrPropertyStore(_, c, _, n.asExpr().(WithExpr), false)
803-
or
804809
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
805810
or
806811
FlowSummaryImpl::Private::storeStep(n, c, _) and
@@ -811,6 +816,13 @@ private module Cached {
811816
input = SummaryInput::parameter(i) and
812817
n.(ArgumentNode).argumentOf(call, i)
813818
)
819+
or
820+
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
821+
oi = we.getInitializer() and
822+
n.asExpr() = oi and
823+
f = oi.getAMemberInitializer().getInitializedMember() and
824+
c = f.getContent()
825+
)
814826
}
815827

816828
/**
@@ -904,6 +916,8 @@ private module Cached {
904916
n instanceof SummaryNodeImpl
905917
or
906918
n instanceof ParamsArgumentNode
919+
or
920+
n.asExpr() = any(WithExpr we).getInitializer()
907921
}
908922
}
909923

csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,17 @@ edges
239239
| I.cs:39:9:39:9 | access to parameter i [Field1] : Object | I.cs:40:14:40:14 | access to parameter i [Field1] : Object |
240240
| I.cs:40:14:40:14 | access to parameter i [Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
241241
| J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:13:48:13:48 | access to local variable o : Object |
242+
| J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:21:36:21:36 | access to local variable o : Object |
242243
| J.cs:13:38:13:50 | { ..., ... } [Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [Prop1] : Object |
243244
| J.cs:13:38:13:50 | { ..., ... } [Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [Prop1] : Object |
244-
| J.cs:13:38:13:50 | { ..., ... } [Prop1] : Object | J.cs:21:18:21:38 | ... with { ... } [Prop1] : Object |
245+
| J.cs:13:38:13:50 | { ..., ... } [Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [Prop1] : Object |
245246
| J.cs:13:48:13:48 | access to local variable o : Object | J.cs:13:38:13:50 | { ..., ... } [Prop1] : Object |
246247
| J.cs:14:14:14:15 | access to local variable r1 [Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
247248
| J.cs:18:14:18:15 | access to local variable r2 [Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
248-
| J.cs:21:18:21:38 | ... with { ... } [Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [Prop1] : Object |
249+
| J.cs:21:18:21:38 | ... with { ... } [Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [Prop2] : Object |
250+
| J.cs:21:36:21:36 | access to local variable o : Object | J.cs:21:18:21:38 | ... with { ... } [Prop2] : Object |
249251
| J.cs:22:14:22:15 | access to local variable r3 [Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
252+
| J.cs:23:14:23:15 | access to local variable r3 [Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
250253
nodes
251254
| A.cs:5:17:5:23 | object creation of type C : C | semmle.label | object creation of type C : C |
252255
| A.cs:6:17:6:25 | call to method Make [c] : C | semmle.label | call to method Make [c] : C |
@@ -529,9 +532,12 @@ nodes
529532
| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
530533
| J.cs:18:14:18:15 | access to local variable r2 [Prop1] : Object | semmle.label | access to local variable r2 [Prop1] : Object |
531534
| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
532-
| J.cs:21:18:21:38 | ... with { ... } [Prop1] : Object | semmle.label | ... with { ... } [Prop1] : Object |
535+
| J.cs:21:18:21:38 | ... with { ... } [Prop2] : Object | semmle.label | ... with { ... } [Prop2] : Object |
536+
| J.cs:21:36:21:36 | access to local variable o : Object | semmle.label | access to local variable o : Object |
533537
| J.cs:22:14:22:15 | access to local variable r3 [Prop1] : Object | semmle.label | access to local variable r3 [Prop1] : Object |
534538
| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
539+
| J.cs:23:14:23:15 | access to local variable r3 [Prop2] : Object | semmle.label | access to local variable r3 [Prop2] : Object |
540+
| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
535541
#select
536542
| A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:23 | object creation of type C : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:23 | object creation of type C : C | object creation of type C : C |
537543
| A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:22 | object creation of type C1 : C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:22 | object creation of type C1 : C1 | object creation of type C1 : C1 |
@@ -588,3 +594,4 @@ nodes
588594
| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object |
589595
| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object |
590596
| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object |
597+
| J.cs:23:14:23:21 | access to property Prop2 | J.cs:12:17:12:28 | object creation of type Object : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:12:17:12:28 | object creation of type Object : Object | object creation of type Object : Object |

0 commit comments

Comments
 (0)