Skip to content

Commit 1785086

Browse files
authored
Merge pull request #15784 from egregius313/egregius313/csharp/dataflow/sources/file
C#: Add source models for `file` threat model/source kind for .NET standard library
2 parents f48e295 + c7a746e commit 1785086

File tree

9 files changed

+208
-34
lines changed

9 files changed

+208
-34
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+
* Additional models have been added for `System.IO`. These are primarily source models with the `file` threat model, and summaries related to reading from a file or stream.

csharp/ql/lib/ext/System.IO.model.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,25 @@ extensions:
77
- ["System.IO", "File", False, "Create", "", "", "ReturnValue", "file-write", "manual"]
88
- ["System.IO", "File", False, "CreateText", "", "", "ReturnValue", "file-write", "manual"]
99
- ["System.IO", "File", False, "Open", "", "", "ReturnValue", "file-write", "manual"]
10+
- ["System.IO", "File", False, "Open", "", "", "ReturnValue", "file", "manual"]
11+
- ["System.IO", "File", False, "OpenRead", "", "", "ReturnValue", "file", "manual"]
12+
- ["System.IO", "File", False, "OpenText", "", "", "ReturnValue", "file", "manual"]
1013
- ["System.IO", "File", False, "OpenWrite", "", "", "ReturnValue", "file-write", "manual"]
14+
- ["System.IO", "File", False, "ReadAllBytes", "", "", "ReturnValue", "file", "manual"]
15+
- ["System.IO", "File", False, "ReadAllBytesAsync", "", "", "ReturnValue", "file", "manual"]
16+
- ["System.IO", "File", False, "ReadAllLines", "", "", "ReturnValue", "file", "manual"]
17+
- ["System.IO", "File", False, "ReadAllLinesAsync", "", "", "ReturnValue", "file", "manual"]
18+
- ["System.IO", "File", False, "ReadAllText", "", "", "ReturnValue", "file", "manual"]
19+
- ["System.IO", "File", False, "ReadAllTextAsync", "", "", "ReturnValue", "file", "manual"]
20+
- ["System.IO", "File", False, "ReadLines", "", "", "ReturnValue", "file", "manual"]
21+
- ["System.IO", "File", False, "ReadLinesAsync", "", "", "ReturnValue", "file", "manual"]
1122
- ["System.IO", "FileInfo", False, "AppendText", "", "", "ReturnValue", "file-write", "manual"]
1223
- ["System.IO", "FileInfo", False, "Create", "", "", "ReturnValue", "file-write", "manual"]
1324
- ["System.IO", "FileInfo", False, "CreateText", "", "", "ReturnValue", "file-write", "manual"]
1425
- ["System.IO", "FileInfo", False, "Open", "", "", "ReturnValue", "file-write", "manual"]
26+
- ["System.IO", "FileInfo", False, "Open", "", "", "ReturnValue", "file", "manual"]
27+
- ["System.IO", "FileInfo", False, "OpenRead", "", "", "ReturnValue", "file", "manual"]
28+
- ["System.IO", "FileInfo", False, "OpenText", "", "", "ReturnValue", "file", "manual"]
1529
- ["System.IO", "FileInfo", False, "OpenWrite", "", "", "ReturnValue", "file-write", "manual"]
1630
- ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file", "manual"]
1731
- ["System.IO", "FileStream", False, "FileStream", "", "", "Argument[this]", "file-write", "manual"]
@@ -25,6 +39,8 @@ extensions:
2539
pack: codeql/csharp-all
2640
extensible: summaryModel
2741
data:
42+
- ["System.IO", "BufferedStream", False, "BufferedStream", "(System.IO.Stream)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
43+
- ["System.IO", "BufferedStream", False, "BufferedStream", "(System.IO.Stream,System.Int32)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
2844
- ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
2945
- ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode,System.IO.FileAccess)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
3046
- ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
@@ -69,8 +85,16 @@ extensions:
6985
- ["System.IO", "Stream", True, "CopyToAsync", "(System.IO.Stream,System.Int32,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0]", "taint", "manual"]
7086
- ["System.IO", "Stream", False, "CopyToAsync", "(System.IO.Stream,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0]", "taint", "manual"]
7187
- ["System.IO", "Stream", True, "Read", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
88+
- ["System.IO", "Stream", True, "Read", "(System.Span<System.Byte>)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
7289
- ["System.IO", "Stream", False, "ReadAsync", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
7390
- ["System.IO", "Stream", True, "ReadAsync", "(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
91+
# Post-update nodes for `Memory<T>` are currently unsupported. This model is provided for completeness
92+
- ["System.IO", "Stream", True, "ReadAsync", "(System.Memory<System.Byte>,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
93+
- ["System.IO", "Stream", True, "ReadAtLeast", "(System.Span<System.Byte>,System.Int32,System.Boolean)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
94+
# Post-update nodes for `Memory<T>` are currently unsupported. This model is provided for completeness
95+
- ["System.IO", "Stream", True, "ReadAtLeastAsync", "(System.Memory<System.Byte>,System.Int32,System.Boolean,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0]", "taint", "manual"]
96+
- ["System.IO", "Stream", True, "ReadExactly", "(System.Span<System.Byte>)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
97+
- ["System.IO", "Stream", True, "ReadExactly", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
7498
- ["System.IO", "Stream", True, "Write", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
7599
- ["System.IO", "Stream", False, "WriteAsync", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
76100
- ["System.IO", "Stream", True, "WriteAsync", "(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System.IO;
2+
3+
namespace Test
4+
{
5+
class Files
6+
{
7+
public static void ReadAllText(string path)
8+
{
9+
string text = File.ReadAllText(path);
10+
Sink(text); // $ hasTaintFlow=line:9
11+
}
12+
13+
public static void ReadAllLines(string path)
14+
{
15+
string[] lines = File.ReadAllLines(path);
16+
Sink(lines); // $ hasTaintFlow=line:15
17+
}
18+
19+
public static void ReadAllBytes(string path)
20+
{
21+
byte[] bytes = File.ReadAllBytes(path);
22+
Sink(bytes); // $ hasTaintFlow=line:21
23+
}
24+
25+
public static void ReadLines(string path)
26+
{
27+
foreach (string line in File.ReadLines(path))
28+
{
29+
Sink(line); // $ hasTaintFlow=line:27
30+
}
31+
}
32+
33+
public static void BufferedRead(string path)
34+
{
35+
using (FileStream fs = new FileStream(path, FileMode.Open))
36+
{
37+
using (BufferedStream bs = new BufferedStream(fs))
38+
{
39+
using (StreamReader sr = new StreamReader(bs))
40+
{
41+
string line;
42+
while ((line = sr.ReadLine()) != null)
43+
{
44+
Sink(line); // $ hasTaintFlow=line:35
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
public static void ReadBlocks(string path)
52+
{
53+
using (FileStream fs = File.OpenRead(path))
54+
{
55+
byte[] buffer = new byte[1024];
56+
int bytesRead;
57+
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
58+
{
59+
Sink(buffer[0]); // $ hasTaintFlow=line:53
60+
}
61+
}
62+
}
63+
64+
public static async void ReadAllTextAsync(string path)
65+
{
66+
string text = await File.ReadAllTextAsync(path);
67+
Sink(text); // $ hasTaintFlow=line:66
68+
69+
using (FileStream fs = File.Open(path, FileMode.Open))
70+
{
71+
using (StreamReader sr = new StreamReader(fs))
72+
{
73+
string line;
74+
while ((line = await sr.ReadLineAsync()) != null)
75+
{
76+
Sink(line); // $ hasTaintFlow=line:69
77+
}
78+
}
79+
}
80+
}
81+
82+
static void Sink(object o) { }
83+
}
84+
}

csharp/ql/test/library-tests/dataflow/flowsources/stored/file/Files.expected

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extensions:
2+
3+
- addsTo:
4+
pack: codeql/threat-models
5+
extensible: threatModelConfiguration
6+
data:
7+
- ["file", true, 0]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import csharp
2+
import semmle.code.csharp.security.dataflow.flowsources.FlowSources
3+
import TestUtilities.InlineFlowTest
4+
import TaintFlowTest<FilesConfig>
5+
6+
module FilesConfig implements DataFlow::ConfigSig {
7+
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
8+
9+
predicate isSink(DataFlow::Node sink) {
10+
exists(MethodCall mc | mc.getTarget().hasName("Sink") | sink.asExpr() = mc.getArgument(0))
11+
}
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
semmle-extractor-options: /nostdlib /noconfig
2+
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
3+
semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs

0 commit comments

Comments
 (0)