Skip to content

Commit 92b773d

Browse files
committed
WIP: C#6 initializers
1 parent 2c229e8 commit 92b773d

9 files changed

Lines changed: 147 additions & 95 deletions

File tree

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

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ module LocalFlow {
118118
) and
119119
scope = e2 and
120120
isSuccessor = true
121+
or
122+
e1 = e2.(ObjectCreation).getInitializer() and
123+
scope = e2 and
124+
isSuccessor = false
125+
or
126+
e1 = e2.(ArrayCreation).getInitializer() and
127+
scope = e2 and
128+
isSuccessor = false
121129
)
122130
}
123131

@@ -303,14 +311,15 @@ private class Argument extends Expr {
303311
/**
304312
* Holds if `e` is an assignment of `src` to field or property `c` of `q`.
305313
*/
306-
private predicate fieldOrPropertyAssign(Expr e, Content c, Expr src, Expr q) {
314+
private predicate fieldOrPropertyAssign(Expr e, Content c, Expr src, Expr q, boolean postUpdate) {
307315
exists(FieldOrPropertyAccess fa, FieldOrProperty f, AssignableDefinition def |
308316
def.getTargetAccess() = fa and
309317
f = fa.getTarget() and
310318
c = f.getContent() and
311319
src = def.getSource() and
312320
q = fa.getQualifier() and
313-
e = def.getExpr()
321+
e = def.getExpr() and
322+
postUpdate = true
314323
|
315324
f.isFieldLike() and
316325
f instanceof InstanceFieldOrProperty
@@ -320,18 +329,14 @@ private predicate fieldOrPropertyAssign(Expr e, Content c, Expr src, Expr q) {
320329
ap.contains(f.getContent())
321330
)
322331
)
323-
}
324-
325-
/**
326-
* Holds if `oc` has an object initializer that assigns `src` to field or
327-
* property `c`.
328-
*/
329-
private predicate fieldOrPropertyInit(ObjectCreation oc, Content c, Expr src) {
332+
or
330333
exists(MemberInitializer mi, FieldOrProperty f |
331-
mi = oc.getInitializer().(ObjectInitializer).getAMemberInitializer() and
334+
e = q and
335+
mi = q.(ObjectInitializer).getAMemberInitializer() and
332336
f = mi.getInitializedMember() and
333337
c = f.getContent() and
334-
src = mi.getRValue()
338+
src = mi.getRValue() and
339+
postUpdate = false
335340
|
336341
f.isFieldLike() and
337342
f instanceof InstanceFieldOrProperty
@@ -371,19 +376,27 @@ private predicate fieldOrPropertyRead(Expr e1, Content c, FieldOrPropertyRead e2
371376
}
372377

373378
/** Holds if `e` is an expression that adds `src` to array `a`. */
374-
private predicate arrayAdd(Expr e, Expr src, Expr a) {
379+
private predicate arrayAdd(Expr e, Expr src, Expr a, boolean postUpdate) {
375380
exists(AssignableDefinition def |
376381
a = def.getTargetAccess().(ArrayWrite).getQualifier() and
377382
src = def.getSource() and
378-
e = def.getExpr()
383+
e = def.getExpr() and
384+
postUpdate = true
385+
)
386+
or
387+
src = a.(ArrayInitializer).getAnElement() and
388+
e = a and
389+
postUpdate = false
390+
or
391+
exists(MemberInitializer mi |
392+
mi = a.(ObjectInitializer).getAMemberInitializer() and
393+
mi.getLValue() instanceof ArrayAccess and
394+
mi.getRValue() = src and
395+
e = a and
396+
postUpdate = false
379397
)
380398
}
381399

382-
/**
383-
* Holds if `ac` is an an arrary creation that adds `src` to the created array.
384-
*/
385-
private predicate arrayInit(ArrayCreation ac, Expr src) { src = ac.getInitializer().getAnElement() }
386-
387400
/**
388401
* Holds if `e2` is an expression that reads an array element from
389402
* from expresion `e1`.
@@ -459,9 +472,9 @@ private module Cached {
459472
t = any(TypeParameter tp | not tp.isValueType())
460473
)
461474
or
462-
fieldOrPropertyAssign(_, _, _, cfn.getElement())
475+
fieldOrPropertyAssign(_, _, _, cfn.getElement(), true)
463476
or
464-
arrayAdd(_, _, cfn.getElement())
477+
arrayAdd(_, _, cfn.getElement(), true)
465478
or
466479
exists(TExprPostUpdateNode upd, FieldOrPropertyAccess fla |
467480
upd = TExprPostUpdateNode(fla.getAControlFlowNode())
@@ -545,19 +558,13 @@ private module Cached {
545558
*/
546559
cached
547560
predicate storeStepImpl(Node node1, Content c, Node node2) {
548-
exists(StoreStepConfiguration x, ExprNode preNode2 |
549-
preNode2 = node2.(PostUpdateNode).getPreUpdateNode() and
550-
x.hasNodePath(node1, preNode2)
561+
exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
562+
x.hasNodePath(node1, node) and
563+
if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
551564
|
552-
fieldOrPropertyAssign(_, c, node1.asExpr(), preNode2.getExpr())
553-
or
554-
arrayAdd(_, node1.asExpr(), preNode2.getExpr()) and c instanceof ElementContent
555-
)
556-
or
557-
exists(StoreStepConfiguration x | x.hasNodePath(node1, node2) |
558-
fieldOrPropertyInit(node2.(ObjectCreationNode).getExpr(), c, node1.asExpr())
565+
fieldOrPropertyAssign(_, c, node1.asExpr(), node.getExpr(), postUpdate)
559566
or
560-
arrayInit(node2.asExpr(), node1.asExpr()) and c instanceof ElementContent
567+
arrayAdd(_, node1.asExpr(), node.getExpr(), postUpdate) and c instanceof ElementContent
561568
)
562569
or
563570
exists(StoreStepConfiguration x, Expr arg, ControlFlow::Node callCfn |
@@ -1751,22 +1758,10 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
17511758
Expr e1, Expr e2, ControlFlowElement scope, boolean exactScope, boolean isSuccessor
17521759
) {
17531760
exactScope = false and
1754-
isSuccessor = false and
1755-
fieldOrPropertyAssign(scope, _, e1, e2)
1761+
fieldOrPropertyAssign(scope, _, e1, e2, isSuccessor.booleanNot())
17561762
or
17571763
exactScope = false and
1758-
isSuccessor = false and
1759-
fieldOrPropertyInit(e2, _, e1) and
1760-
scope = e2
1761-
or
1762-
exactScope = false and
1763-
isSuccessor = false and
1764-
arrayAdd(scope, e1, e2)
1765-
or
1766-
exactScope = false and
1767-
isSuccessor = false and
1768-
arrayInit(e2, e1) and
1769-
scope = e2
1764+
arrayAdd(scope, e1, e2, isSuccessor.booleanNot())
17701765
or
17711766
exactScope = false and
17721767
isSuccessor = true and

csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public void ArrayInitializerCSharp6Flow()
3131
{
3232
var a = new A();
3333
var c = new CollectionFlow() { As = { [0] = a } };
34-
Sink(c.As[0]); // flow [MISSING]
35-
SinkElem(c.As); // flow [MISSING]
36-
Sink(First(c.As)); // flow [MISSING]
34+
Sink(c.As[0]); // flow
35+
SinkElem(c.As); // flow
36+
Sink(First(c.As)); // flow
3737
}
3838

3939
public void ArrayInitializerCSharp6NoFlow(A other)

0 commit comments

Comments
 (0)