Skip to content

Commit eb1474a

Browse files
authored
Merge pull request github#3276 from hvitved/csharp/dataflow/array-tests
C#: Add data-flow test for collections
2 parents 243dea7 + e186c9d commit eb1474a

File tree

3 files changed

+489
-0
lines changed

3 files changed

+489
-0
lines changed
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// semmle-extractor-options: /r:System.Linq.dll
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
public class CollectionFlow
7+
{
8+
public class A { }
9+
10+
public void ArrayInitializerFlow()
11+
{
12+
var a = new A();
13+
var @as = new[] { a };
14+
Sink(@as[0]); // flow
15+
SinkElem(@as); // flow
16+
Sink(First(@as)); // flow
17+
}
18+
19+
public void ArrayInitializerNoFlow(A other)
20+
{
21+
var a = new A();
22+
var @as = new[] { other };
23+
Sink(@as[0]); // no flow
24+
SinkElem(@as); // no flow
25+
Sink(First(@as)); // no flow
26+
}
27+
28+
public void ArrayAssignmentFlow()
29+
{
30+
var a = new A();
31+
var @as = new A[1];
32+
@as[0] = a;
33+
Sink(@as[0]); // flow
34+
SinkElem(@as); // flow
35+
Sink(First(@as)); // flow
36+
}
37+
38+
public void ArrayAssignmentNoFlow(A other)
39+
{
40+
var a = new A();
41+
var @as = new A[1];
42+
@as[0] = other;
43+
Sink(@as[0]); // no flow
44+
SinkElem(@as); // no flow
45+
Sink(First(@as)); // no flow
46+
}
47+
48+
public void ListAssignmentFlow()
49+
{
50+
var a = new A();
51+
var list = new List<A>();
52+
list[0] = a;
53+
Sink(list[0]); // flow
54+
SinkListElem(list); // flow
55+
Sink(ListFirst(list)); // flow
56+
}
57+
58+
public void ListAssignmentNoFlow(A other)
59+
{
60+
var list = new List<A>();
61+
list[0] = other;
62+
Sink(list[0]); // no flow
63+
SinkListElem(list); // no flow
64+
Sink(ListFirst(list)); // no flow
65+
}
66+
67+
public void ListInitializerFlow()
68+
{
69+
var a = new A();
70+
var list = new List<A>() { a };
71+
Sink(list[0]); // flow
72+
SinkListElem(list); // flow
73+
Sink(ListFirst(list)); // flow
74+
}
75+
76+
public void ListInitializerNoFlow(A other)
77+
{
78+
var list = new List<A>() { other };
79+
Sink(list[0]); // no flow
80+
SinkListElem(list); // no flow
81+
Sink(ListFirst(list)); // no flow
82+
}
83+
84+
public void ListAddFlow()
85+
{
86+
var a = new A();
87+
var list = new List<A>();
88+
list.Add(a);
89+
Sink(list[0]); // flow
90+
SinkListElem(list); // flow
91+
Sink(ListFirst(list)); // flow
92+
}
93+
94+
public void ListAddNoFlow(A other)
95+
{
96+
var list = new List<A>();
97+
list.Add(other);
98+
Sink(list[0]); // no flow
99+
SinkListElem(list); // no flow
100+
Sink(ListFirst(list)); // no flow
101+
}
102+
103+
public void DictionaryAssignmentFlow()
104+
{
105+
var a = new A();
106+
var dict = new Dictionary<int, A>();
107+
dict[0] = a;
108+
Sink(dict[0]); // flow
109+
SinkDictValue(dict); // flow
110+
Sink(DictIndexZero(dict)); // flow
111+
Sink(DictFirstValue(dict)); // flow [MISSING]
112+
Sink(DictValuesFirst(dict)); // flow
113+
}
114+
115+
public void DictionaryAssignmentNoFlow(A other)
116+
{
117+
var dict = new Dictionary<int, A>();
118+
dict[0] = other;
119+
Sink(dict[0]); // no flow
120+
SinkDictValue(dict); // no flow
121+
Sink(DictIndexZero(dict)); // no flow
122+
Sink(DictFirstValue(dict)); // no flow
123+
Sink(DictValuesFirst(dict)); // no flow
124+
}
125+
126+
public void DictionaryValueInitializerFlow()
127+
{
128+
var a = new A();
129+
var dict = new Dictionary<int, A>() { { 0, a } };
130+
Sink(dict[0]); // flow
131+
SinkDictValue(dict); // flow
132+
Sink(DictIndexZero(dict)); // flow
133+
Sink(DictFirstValue(dict)); // flow [MISSING]
134+
Sink(DictValuesFirst(dict)); // flow
135+
}
136+
137+
public void DictionaryValueInitializerNoFlow(A other)
138+
{
139+
var dict = new Dictionary<int, A>() { { 0, other } };
140+
Sink(dict[0]); // no flow
141+
SinkDictValue(dict); // no flow
142+
Sink(DictIndexZero(dict)); // no flow
143+
Sink(DictFirstValue(dict)); // no flow
144+
Sink(DictValuesFirst(dict)); // no flow
145+
}
146+
147+
public void DictionaryKeyInitializerFlow()
148+
{
149+
var a = new A();
150+
var dict = new Dictionary<A, int>() { { a, 0 } };
151+
Sink(dict.Keys.First()); // flow [MISSING]
152+
SinkDictKey(dict); // flow [MISSING]
153+
Sink(DictKeysFirst(dict)); // flow [MISSING]
154+
Sink(DictFirstKey(dict)); // flow [MISSING]
155+
}
156+
157+
public void DictionaryKeyInitializerNoFlow(A other)
158+
{
159+
var dict = new Dictionary<A, int>() { { other, 0 } };
160+
Sink(dict.Keys.First()); // no flow
161+
SinkDictKey(dict); // no flow
162+
Sink(DictKeysFirst(dict)); // no flow
163+
Sink(DictFirstKey(dict)); // no flow
164+
}
165+
166+
public void ForeachFlow()
167+
{
168+
var a = new A();
169+
var @as = new[] { a };
170+
foreach (var x in @as)
171+
Sink(x); // flow
172+
}
173+
174+
public void ForeachNoFlow(A other)
175+
{
176+
var @as = new[] { other };
177+
foreach (var x in @as)
178+
Sink(x); // no flow
179+
}
180+
181+
public void ArrayGetEnumeratorFlow()
182+
{
183+
var a = new A();
184+
var @as = new[] { a };
185+
var enumerator = @as.GetEnumerator();
186+
while (enumerator.MoveNext())
187+
Sink(enumerator.Current); // flow
188+
}
189+
190+
public void ArrayGetEnumeratorNoFlow(A other)
191+
{
192+
var @as = new[] { other };
193+
var enumerator = @as.GetEnumerator();
194+
while (enumerator.MoveNext())
195+
Sink(enumerator.Current); // no flow
196+
}
197+
198+
public void ListGetEnumeratorFlow()
199+
{
200+
var a = new A();
201+
var list = new List<A>();
202+
list.Add(a);
203+
var enumerator = list.GetEnumerator();
204+
while (enumerator.MoveNext())
205+
Sink(enumerator.Current); // flow [MISSING]
206+
}
207+
208+
public static void Sink<T>(T t) { }
209+
210+
public static void SinkElem<T>(T[] ts) => Sink(ts[0]);
211+
212+
public static void SinkListElem<T>(IList<T> list) => Sink(list[0]);
213+
214+
public static void SinkDictValue<T>(IDictionary<int, T> dict) => Sink(dict[0]);
215+
216+
public static void SinkDictKey<T>(IDictionary<T, int> dict) => Sink(dict.Keys.First());
217+
218+
public static T First<T>(T[] ts) => ts[0];
219+
220+
public static T ListFirst<T>(IList<T> list) => list[0];
221+
222+
public static T DictIndexZero<T>(IDictionary<int, T> dict) => dict[0];
223+
224+
public static T DictFirstValue<T>(IDictionary<int, T> dict) => dict.First().Value;
225+
226+
public static T DictValuesFirst<T>(IDictionary<int, T> dict) => dict.Values.First();
227+
228+
public static T DictKeysFirst<T>(IDictionary<T, int> dict) => dict.Keys.First();
229+
230+
public static T DictFirstKey<T>(IDictionary<T, int> dict) => dict.First().Key;
231+
}

0 commit comments

Comments
 (0)