Skip to content

Commit c684b74

Browse files
committed
C#: Add async dataflow tests
1 parent c08230c commit c684b74

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Threading.Tasks;
2+
3+
class Test
4+
{
5+
private void Sink(string s)
6+
{
7+
}
8+
9+
public void TestNonAwait(string input)
10+
{
11+
Sink(Return(input)); // True positive
12+
}
13+
14+
private string Return(string x)
15+
{
16+
return x;
17+
}
18+
19+
public async Task TestAwait1(string input)
20+
{
21+
Sink(await ReturnAwait(input)); // False negative
22+
}
23+
24+
public async Task TestAwait2(string input)
25+
{
26+
var x = await ReturnAwait(input);
27+
Sink(x); // False negative
28+
}
29+
30+
public void TestAwait3(string input)
31+
{
32+
Sink(ReturnAwait(input).Result); // False negative
33+
}
34+
35+
private async Task<string> ReturnAwait(string x)
36+
{
37+
await Task.Delay(1);
38+
return x;
39+
}
40+
41+
public void TestTask(string input)
42+
{
43+
Sink(ReturnTask(input).Result); // True positive
44+
}
45+
46+
private Task<string> ReturnTask(string x)
47+
{
48+
return Task.FromResult(x);
49+
}
50+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
edges
2+
| Async.cs:9:37:9:41 | input : String | Async.cs:11:21:11:25 | access to parameter input : String |
3+
| Async.cs:11:21:11:25 | access to parameter input : String | Async.cs:11:14:11:26 | call to method Return |
4+
| Async.cs:14:34:14:34 | x : String | Async.cs:16:16:16:16 | access to parameter x : String |
5+
| Async.cs:16:16:16:16 | access to parameter x : String | Async.cs:11:14:11:26 | call to method Return |
6+
| Async.cs:41:33:41:37 | input : String | Async.cs:43:25:43:29 | access to parameter input : String |
7+
| Async.cs:43:14:43:30 | call to method ReturnTask [Result] : String | Async.cs:43:14:43:37 | access to property Result |
8+
| Async.cs:43:25:43:29 | access to parameter input : String | Async.cs:43:14:43:30 | call to method ReturnTask [Result] : String |
9+
| Async.cs:46:44:46:44 | x : String | Async.cs:48:32:48:32 | access to parameter x : String |
10+
| Async.cs:48:16:48:33 | call to method FromResult [Result] : String | Async.cs:43:14:43:30 | call to method ReturnTask [Result] : String |
11+
| Async.cs:48:32:48:32 | access to parameter x : String | Async.cs:48:16:48:33 | call to method FromResult [Result] : String |
12+
nodes
13+
| Async.cs:9:37:9:41 | input : String | semmle.label | input : String |
14+
| Async.cs:11:14:11:26 | call to method Return | semmle.label | call to method Return |
15+
| Async.cs:11:21:11:25 | access to parameter input : String | semmle.label | access to parameter input : String |
16+
| Async.cs:14:34:14:34 | x : String | semmle.label | x : String |
17+
| Async.cs:16:16:16:16 | access to parameter x : String | semmle.label | access to parameter x : String |
18+
| Async.cs:41:33:41:37 | input : String | semmle.label | input : String |
19+
| Async.cs:43:14:43:30 | call to method ReturnTask [Result] : String | semmle.label | call to method ReturnTask [Result] : String |
20+
| Async.cs:43:14:43:37 | access to property Result | semmle.label | access to property Result |
21+
| Async.cs:43:25:43:29 | access to parameter input : String | semmle.label | access to parameter input : String |
22+
| Async.cs:46:44:46:44 | x : String | semmle.label | x : String |
23+
| Async.cs:48:16:48:33 | call to method FromResult [Result] : String | semmle.label | call to method FromResult [Result] : String |
24+
| Async.cs:48:32:48:32 | access to parameter x : String | semmle.label | access to parameter x : String |
25+
#select
26+
| Async.cs:11:14:11:26 | call to method Return | Async.cs:9:37:9:41 | input : String | Async.cs:11:14:11:26 | call to method Return | $@ flows to here and is used. | Async.cs:9:37:9:41 | input | User-provided value |
27+
| Async.cs:11:14:11:26 | call to method Return | Async.cs:14:34:14:34 | x : String | Async.cs:11:14:11:26 | call to method Return | $@ flows to here and is used. | Async.cs:14:34:14:34 | x | User-provided value |
28+
| Async.cs:43:14:43:37 | access to property Result | Async.cs:41:33:41:37 | input : String | Async.cs:43:14:43:37 | access to property Result | $@ flows to here and is used. | Async.cs:41:33:41:37 | input | User-provided value |
29+
| Async.cs:43:14:43:37 | access to property Result | Async.cs:46:44:46:44 | x : String | Async.cs:43:14:43:37 | access to property Result | $@ flows to here and is used. | Async.cs:46:44:46:44 | x | User-provided value |
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import csharp
2+
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
3+
4+
class MySink extends DataFlow::ExprNode {
5+
MySink() {
6+
exists(Method m, MethodCall mc |
7+
mc.getTarget() = m and
8+
m.getName() = "Sink" and
9+
this.getExpr() = mc.getArgumentForName("s")
10+
)
11+
}
12+
}
13+
14+
class MySource extends DataFlow::ParameterNode {
15+
MySource() {
16+
exists(Parameter p | p = this.getParameter() |
17+
p = any(Class c | c.hasQualifiedName("Test")).getAMethod().getAParameter()
18+
)
19+
}
20+
}
21+
22+
class MyConfig extends TaintTracking::Configuration {
23+
MyConfig() { this = "MyConfig" }
24+
25+
override predicate isSource(DataFlow::Node source) { source instanceof MySource }
26+
27+
override predicate isSink(DataFlow::Node sink) { sink instanceof MySink }
28+
}
29+
30+
from MyConfig c, DataFlow::PathNode source, DataFlow::PathNode sink
31+
where c.hasFlowPath(source, sink)
32+
select sink.getNode(), source, sink, "$@ flows to here and is used.", source.getNode(),
33+
"User-provided value"

0 commit comments

Comments
 (0)