Skip to content

Commit a2f45f1

Browse files
authored
Merge pull request #21383 from michaelnebel/csharp/postupdatenoderestriction
C#: Add post-update nodes for `struct` type argument nodes.
2 parents 16cd3a8 + 319e3d1 commit a2f45f1

File tree

9 files changed

+166
-8
lines changed

9 files changed

+166
-8
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+
* Added post-update nodes for struct-type arguments, allowing data flow out of method calls via those arguments.

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import ControlFlowReachability
66
private import FlowSummaryImpl as FlowSummaryImpl
77
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
88
private import semmle.code.csharp.dataflow.internal.ExternalFlow
9+
private import semmle.code.csharp.commons.Collections
910
private import semmle.code.csharp.Conversion
1011
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
1112
private import semmle.code.csharp.ExprOrStmtParent
@@ -16,7 +17,6 @@ private import semmle.code.csharp.frameworks.EntityFramework
1617
private import semmle.code.csharp.frameworks.system.linq.Expressions
1718
private import semmle.code.csharp.frameworks.NHibernate
1819
private import semmle.code.csharp.frameworks.Razor
19-
private import semmle.code.csharp.frameworks.system.Collections
2020
private import semmle.code.csharp.frameworks.system.threading.Tasks
2121
private import semmle.code.csharp.internal.Location
2222
private import codeql.util.Unit
@@ -1087,7 +1087,7 @@ predicate exprMayHavePostUpdateNode(Expr e) {
10871087
or
10881088
t = any(TypeParameter tp | not tp.isValueType())
10891089
or
1090-
t.isRefLikeType()
1090+
t instanceof Struct
10911091
)
10921092
}
10931093

@@ -2545,6 +2545,7 @@ private predicate clearsCont(Node n, Content c) {
25452545
a.getType() = s and
25462546
f = s.getAField() and
25472547
c.(FieldContent).getField() = f.getUnboundDeclaration() and
2548+
not f.getType() instanceof CollectionType and
25482549
not f.isRef()
25492550
)
25502551
or

csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@
321321
| CSharp7.cs:283:20:283:62 | call to method Select<KeyValuePair<Int32,String>,(Int32,String)> | CSharp7.cs:283:13:283:16 | access to local variable list |
322322
| CSharp7.cs:283:32:283:35 | SSA param(item) | CSharp7.cs:283:41:283:44 | access to parameter item |
323323
| CSharp7.cs:283:32:283:35 | item | CSharp7.cs:283:32:283:35 | SSA param(item) |
324+
| CSharp7.cs:283:41:283:44 | [post] access to parameter item | CSharp7.cs:283:51:283:54 | access to parameter item |
324325
| CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:41:283:48 | access to property Key |
325326
| CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:51:283:54 | access to parameter item |
326327
| CSharp7.cs:283:51:283:54 | access to parameter item | CSharp7.cs:283:51:283:60 | access to property Value |

csharp/ql/test/library-tests/dataflow/external-models/Sources.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ void Foo()
2121

2222
x = TaggedSrcPropertyGetter;
2323
x = this[0];
24+
25+
S s;
26+
StructSrc(s);
2427
}
2528

2629
[SourceAttribute]
@@ -65,7 +68,10 @@ void SrcArg(object src) { }
6568

6669
[SourceAttribute]
6770
object this[int i] => null;
71+
72+
void StructSrc(S s) { }
6873
}
6974

75+
struct S { }
7076
class SourceAttribute : System.Attribute { }
7177
}

csharp/ql/test/library-tests/dataflow/external-models/srcs.expected

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ invalidModelRow
1111
| Sources.cs:20:17:20:33 | call to method SrcTwoArg | local |
1212
| Sources.cs:22:17:22:39 | access to property TaggedSrcPropertyGetter | local |
1313
| Sources.cs:23:17:23:23 | access to indexer | local |
14-
| Sources.cs:27:14:27:20 | this | local |
15-
| Sources.cs:27:29:27:45 | taggedMethodParam | local |
16-
| Sources.cs:31:47:31:60 | taggedSrcParam | local |
17-
| Sources.cs:43:45:43:45 | p | local |
18-
| Sources.cs:50:50:50:50 | p | local |
19-
| Sources.cs:56:16:56:30 | this | local |
14+
| Sources.cs:26:23:26:23 | [post] access to local variable s | local |
15+
| Sources.cs:30:14:30:20 | this | local |
16+
| Sources.cs:30:29:30:45 | taggedMethodParam | local |
17+
| Sources.cs:34:47:34:60 | taggedSrcParam | local |
18+
| Sources.cs:46:45:46:45 | p | local |
19+
| Sources.cs:53:50:53:50 | p | local |
20+
| Sources.cs:59:16:59:30 | this | local |

csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ extensions:
1919
- ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "", "local", "manual"]
2020
- ["My.Qltest", "SourceAttribute", false, "", "", "Attribute.Getter", "ReturnValue", "local", "manual"]
2121
- ["My.Qltest", "A", false, "SrcTwoArg", "(System.String,System.String)", "", "ReturnValue", "local", "manual"]
22+
- ["My.Qltest", "A", false, "StructSrc", "", "", "Argument[0]", "local", "manual"]
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
models
2+
edges
3+
| structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | provenance | |
4+
| structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | provenance | |
5+
| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | provenance | |
6+
| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | provenance | |
7+
| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | provenance | |
8+
| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | provenance | |
9+
| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | provenance | |
10+
| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | provenance | |
11+
| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | provenance | |
12+
| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | provenance | |
13+
| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | provenance | |
14+
| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | provenance | |
15+
| structs.cs:18:21:18:37 | call to method Source<Object> : Object | structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | provenance | |
16+
| structs.cs:18:21:18:37 | call to method Source<Object> : Object | structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | provenance | |
17+
| structs.cs:24:13:24:13 | access to local variable o : Object | structs.cs:25:24:25:24 | access to local variable o : Object | provenance | |
18+
| structs.cs:24:13:24:13 | access to local variable o : Object | structs.cs:25:24:25:24 | access to local variable o : Object | provenance | |
19+
| structs.cs:24:17:24:33 | call to method Source<Object> : Object | structs.cs:24:13:24:13 | access to local variable o : Object | provenance | |
20+
| structs.cs:24:17:24:33 | call to method Source<Object> : Object | structs.cs:24:13:24:13 | access to local variable o : Object | provenance | |
21+
| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | provenance | |
22+
| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | provenance | |
23+
| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | provenance | |
24+
| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | provenance | |
25+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | provenance | |
26+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | provenance | |
27+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | provenance | |
28+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | provenance | |
29+
| structs.cs:25:24:25:24 | access to local variable o : Object | structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | provenance | |
30+
| structs.cs:25:24:25:24 | access to local variable o : Object | structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | provenance | |
31+
| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | provenance | |
32+
| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | provenance | |
33+
| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | structs.cs:26:14:26:22 | access to array element | provenance | |
34+
| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | structs.cs:26:14:26:22 | access to array element | provenance | |
35+
| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | provenance | |
36+
| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | provenance | |
37+
| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | provenance | |
38+
| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | provenance | |
39+
| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | structs.cs:33:14:33:22 | access to array element | provenance | |
40+
| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | structs.cs:33:14:33:22 | access to array element | provenance | |
41+
nodes
42+
| structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | semmle.label | this [Return] : S [field args, element] : Object |
43+
| structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | semmle.label | this [Return] : S [field args, element] : Object |
44+
| structs.cs:10:27:10:30 | args : Object[] [element] : Object | semmle.label | args : Object[] [element] : Object |
45+
| structs.cs:10:27:10:30 | args : Object[] [element] : Object | semmle.label | args : Object[] [element] : Object |
46+
| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | semmle.label | [post] this access : S [field args, element] : Object |
47+
| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | semmle.label | [post] this access : S [field args, element] : Object |
48+
| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | semmle.label | access to parameter args : Object[] [element] : Object |
49+
| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | semmle.label | access to parameter args : Object[] [element] : Object |
50+
| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | semmle.label | s [Return] : S [field args, element] : Object |
51+
| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | semmle.label | s [Return] : S [field args, element] : Object |
52+
| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | semmle.label | [post] access to parameter s : S [field args, element] : Object |
53+
| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | semmle.label | [post] access to parameter s : S [field args, element] : Object |
54+
| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | semmle.label | [post] access to field args : Object[] [element] : Object |
55+
| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | semmle.label | [post] access to field args : Object[] [element] : Object |
56+
| structs.cs:18:21:18:37 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
57+
| structs.cs:18:21:18:37 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
58+
| structs.cs:24:13:24:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
59+
| structs.cs:24:13:24:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
60+
| structs.cs:24:17:24:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
61+
| structs.cs:24:17:24:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
62+
| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object |
63+
| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object |
64+
| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | semmle.label | object creation of type S : S [field args, element] : Object |
65+
| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | semmle.label | object creation of type S : S [field args, element] : Object |
66+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | semmle.label | [...] : Object[] [element] : Object |
67+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | semmle.label | [...] : Object[] [element] : Object |
68+
| structs.cs:25:24:25:24 | access to local variable o : Object | semmle.label | access to local variable o : Object |
69+
| structs.cs:25:24:25:24 | access to local variable o : Object | semmle.label | access to local variable o : Object |
70+
| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object |
71+
| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object |
72+
| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object |
73+
| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object |
74+
| structs.cs:26:14:26:22 | access to array element | semmle.label | access to array element |
75+
| structs.cs:26:14:26:22 | access to array element | semmle.label | access to array element |
76+
| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | semmle.label | [post] access to local variable s : S [field args, element] : Object |
77+
| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | semmle.label | [post] access to local variable s : S [field args, element] : Object |
78+
| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object |
79+
| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object |
80+
| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object |
81+
| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object |
82+
| structs.cs:33:14:33:22 | access to array element | semmle.label | access to array element |
83+
| structs.cs:33:14:33:22 | access to array element | semmle.label | access to array element |
84+
subpaths
85+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object |
86+
| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object |
87+
testFailures
88+
#select
89+
| structs.cs:26:14:26:22 | access to array element | structs.cs:24:17:24:33 | call to method Source<Object> : Object | structs.cs:26:14:26:22 | access to array element | $@ | structs.cs:24:17:24:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
90+
| structs.cs:26:14:26:22 | access to array element | structs.cs:24:17:24:33 | call to method Source<Object> : Object | structs.cs:26:14:26:22 | access to array element | $@ | structs.cs:24:17:24:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
91+
| structs.cs:33:14:33:22 | access to array element | structs.cs:18:21:18:37 | call to method Source<Object> : Object | structs.cs:33:14:33:22 | access to array element | $@ | structs.cs:18:21:18:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |
92+
| structs.cs:33:14:33:22 | access to array element | structs.cs:18:21:18:37 | call to method Source<Object> : Object | structs.cs:33:14:33:22 | access to array element | $@ | structs.cs:18:21:18:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @kind path-problem
3+
*/
4+
5+
import csharp
6+
import utils.test.InlineFlowTest
7+
import DefaultFlowTest
8+
import PathGraph
9+
10+
from PathNode source, PathNode sink
11+
where flowPath(source, sink)
12+
select sink, source, sink, "$@", source, source.toString()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
3+
public class Test
4+
{
5+
public struct S
6+
{
7+
public int field;
8+
public object[] args;
9+
10+
public S(object[] args)
11+
{
12+
this.args = args;
13+
}
14+
}
15+
16+
public void SetTainted(S s)
17+
{
18+
s.args[0] = Source<object>(2);
19+
s.field = Source<int>(3);
20+
}
21+
22+
public void M1()
23+
{
24+
var o = Source<object>(1);
25+
var s = new S([o]);
26+
Sink(s.args[0]); // $ hasValueFlow=1
27+
}
28+
29+
public void M2()
30+
{
31+
var s = new S(new object[1]);
32+
SetTainted(s);
33+
Sink(s.args[0]); // $ hasValueFlow=2
34+
Sink(s.field); // $ no flow.
35+
}
36+
37+
public static void Sink(object o) { }
38+
39+
static T Source<T>(object source) => throw null;
40+
}

0 commit comments

Comments
 (0)