Skip to content

Commit 74f483a

Browse files
committed
C#: Update model conversion queries
1 parent 6f4311d commit 74f483a

File tree

8 files changed

+101
-57
lines changed

8 files changed

+101
-57
lines changed

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

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -371,46 +371,49 @@ private string paramsString(InterpretedCallable c) {
371371
)
372372
}
373373

374+
/** Gets the source/sink/summary/neutral base declaration corresponding to the supplied parameters. */
374375
pragma[nomagic]
375-
private Element interpretElement0(
376-
string namespace, string type, boolean subtypes, string name, string signature
377-
) {
378-
exists(UnboundValueOrRefType t | elementSpec(namespace, type, subtypes, name, signature, _, t) |
379-
exists(Declaration m |
380-
(
381-
result = m
382-
or
383-
subtypes = true and result.(UnboundCallable).overridesOrImplementsUnbound(m)
384-
) and
385-
m.getDeclaringType() = t and
386-
hasName(m, name)
387-
|
388-
signature = ""
389-
or
390-
paramsString(m) = signature
391-
)
376+
Declaration interpretBaseDeclaration(string namespace, string type, string name, string signature) {
377+
exists(UnboundValueOrRefType t | elementSpec(namespace, type, _, name, signature, _, t) |
378+
result =
379+
any(Declaration d |
380+
d.getDeclaringType() = t and
381+
hasName(d, name) and
382+
(
383+
signature = ""
384+
or
385+
paramsString(d) = signature
386+
)
387+
)
392388
or
393-
(
394-
result = t
395-
or
396-
subtypes = true and
397-
result = t.getASubTypeUnbound+()
398-
) and
399389
result = t and
400390
name = "" and
401391
signature = ""
402392
)
403393
}
404394

405395
/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
396+
pragma[nomagic]
406397
Element interpretElement(
407398
string namespace, string type, boolean subtypes, string name, string signature, string ext
408399
) {
409400
elementSpec(namespace, type, subtypes, name, signature, ext) and
410-
exists(Element e | e = interpretElement0(namespace, type, subtypes, name, signature) |
411-
ext = "" and result = e
401+
exists(Declaration base, Declaration d |
402+
base = interpretBaseDeclaration(namespace, type, name, signature) and
403+
(
404+
d = base
405+
or
406+
subtypes = true and
407+
(
408+
d.(UnboundCallable).overridesOrImplementsUnbound(base)
409+
or
410+
d = base.(UnboundValueOrRefType).getASubTypeUnbound+()
411+
)
412+
)
413+
|
414+
ext = "" and result = d
412415
or
413-
ext = "Attribute" and result.(Attributable).getAnAttribute().getType() = e
416+
ext = "Attribute" and result.(Attributable).getAnAttribute().getType() = d
414417
)
415418
}
416419

@@ -491,7 +494,7 @@ string parameterQualifiedTypeNamesToString(Callable c) {
491494
concat(int i, string s | s = parameterQualifiedType(c.getParameter(i)) | s, "," order by i)
492495
}
493496

494-
private predicate partialModel(
497+
predicate partialModel(
495498
UnboundCallable c, string namespace, string type, string name, string parameters
496499
) {
497500
QN::hasQualifiedName(c, namespace, type, name) and

csharp/ql/src/utils/modelconverter/ConvertExtensions.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@
2727
dbDir = os.path.join(workDir, "db")
2828

2929
# Make dummy project
30-
helpers.run_cmd(['dotnet', 'new', 'console', '-o', projectDir], "Failed to create dummy project.")
30+
helpers.run_cmd(['dotnet', 'new', 'webapp', '-o', projectDir], "Failed to create dummy project.")
31+
# Add nuget packages for all packages where we have models
32+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'Newtonsoft.Json'])
33+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'Microsoft.EntityFrameworkCore'])
34+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'Microsoft.EntityFrameworkCore.Relational'])
35+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'Dapper'])
36+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'ServiceStack'])
37+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'ServiceStack.OrmLite'])
38+
helpers.run_cmd(['dotnet', 'add', projectDir, 'package', 'System.Collections.Immutable'])
3139
helpers.run_cmd(['codeql', 'database', 'create', f'--language={language}', '-c', f'dotnet build {projectDir}', dbDir], "Failed to create dummy database.")
3240

3341
print('Converting data extensions for C#.')

csharp/ql/src/utils/modelconverter/ExtractNeutrals.ql

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
*/
66

77
import csharp
8-
import semmle.code.csharp.dataflow.internal.ExternalFlow
8+
import InterpretModel
99

10-
from string package, string type, string name, string signature, string kind, string provenance
10+
from
11+
string namespace0, string namespace, string type0, string type, string name0, string name,
12+
string signature0, string signature, string kind, string provenance
1113
where
12-
neutralModel(package, type, name, signature, kind, provenance) and
13-
not provenance.matches("%generated")
14-
select package, type, name, signature, kind, provenance order by
15-
package, type, name, signature, kind
14+
neutralModel(namespace0, type0, name0, signature0, kind, provenance) and
15+
interpretCallable(namespace0, namespace, type0, type, name0, name, signature0, signature)
16+
select namespace, type, name, signature, kind, provenance order by
17+
namespace, type, name, signature, kind

csharp/ql/src/utils/modelconverter/ExtractSinks.ql

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
*/
66

77
import csharp
8-
import semmle.code.csharp.dataflow.internal.ExternalFlow
8+
import InterpretModel
99

1010
from
11-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
12-
string input, string kind, string provenance
11+
string namespace0, string namespace, string type0, string type, boolean subtypes, string name0,
12+
string name, string signature0, string signature, string ext, string input, string kind,
13+
string provenance
1314
where
14-
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) and
15-
not provenance.matches("%generated")
15+
sinkModel(namespace0, type0, subtypes, name0, signature0, ext, input, kind, provenance) and
16+
interpretCallable(namespace0, namespace, type0, type, name0, name, signature0, signature)
1617
select namespace, type, subtypes, name, signature, ext, input, kind, provenance order by
1718
namespace, type, name, signature, input, kind

csharp/ql/src/utils/modelconverter/ExtractSources.ql

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
*/
66

77
import csharp
8-
import semmle.code.csharp.dataflow.internal.ExternalFlow
8+
import InterpretModel
99

1010
from
11-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
12-
string output, string kind, string provenance
11+
string namespace0, string namespace, string type0, string type, boolean subtypes, string name0,
12+
string name, string signature0, string signature, string ext, string output, string kind,
13+
string provenance
1314
where
14-
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
15-
not provenance.matches("%generated")
15+
sourceModel(namespace0, type0, subtypes, name0, signature0, ext, output, kind, provenance) and
16+
interpretCallable(namespace0, namespace, type0, type, name0, name, signature0, signature)
1617
select namespace, type, subtypes, name, signature, ext, output, kind, provenance order by
1718
namespace, type, name, signature, output, kind

csharp/ql/src/utils/modelconverter/ExtractSummaries.ql

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
*/
66

77
import csharp
8-
import semmle.code.csharp.dataflow.internal.ExternalFlow
8+
import InterpretModel
99

1010
from
11-
string namespace, string type, boolean subtypes, string name, string signature, string ext,
12-
string input, string output, string kind, string provenance
11+
string namespace0, string namespace, string type0, string type, boolean subtypes, string name0,
12+
string name, string signature0, string signature, string ext, string input, string output,
13+
string kind, string provenance
1314
where
14-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
15-
not provenance.matches("%generated")
15+
summaryModel(namespace0, type0, subtypes, name0, signature0, ext, input, output, kind, provenance) and
16+
interpretCallable(namespace0, namespace, type0, type, name0, name, signature0, signature)
1617
select namespace, type, subtypes, name, signature, ext, input, output, kind, provenance order by
1718
namespace, type, name, signature, input, output, kind
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import csharp
2+
import semmle.code.csharp.dataflow.internal.ExternalFlow
3+
4+
bindingset[namespace0, type0, name0, signature0]
5+
predicate interpretCallable(
6+
string namespace0, string namespace, string type0, string type, string name0, string name,
7+
string signature0, string signature
8+
) {
9+
exists(Callable c, string signature1 |
10+
c = interpretBaseDeclaration(namespace0, type0, name0, signature0) and
11+
partialModel(c, namespace, type, name, signature1) and
12+
if signature0 = "" then signature = "" else signature = signature1
13+
)
14+
or
15+
// if the row cannot be parsed (e.g. if the element is not in the DB), return the existing row unchanged
16+
not exists(interpretBaseDeclaration(namespace0, type0, name0, signature0)) and
17+
namespace = namespace0 and
18+
type = type0 and
19+
name = name0 and
20+
signature = signature0
21+
}

misc/scripts/models-as-data/convert_extensions.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ def merge(*dicts):
2929
return merged
3030

3131
def parseData(data):
32-
rows = { }
32+
rows = [{ }, { }]
3333
for row in data:
3434
d = map(quote_if_needed, row)
35-
insert_update(rows, row[0], " - [" + ', '.join(d) + ']\n')
35+
provenance = row[-1]
36+
targetRows = rows[1] if provenance.endswith("generated") else rows[0]
37+
insert_update(targetRows, row[0], " - [" + ', '.join(d) + ']\n')
3638

3739
return rows
3840

@@ -57,9 +59,10 @@ def runQuery(self, query):
5759

5860

5961
def asAddsTo(self, rows, predicate):
60-
extensions = { }
61-
for key in rows:
62-
extensions[key] = helpers.addsToTemplate.format(f"codeql/{self.language}-all", predicate, rows[key])
62+
extensions = [{ }, { }]
63+
for i in range(2):
64+
for key in rows[i]:
65+
extensions[i][key] = helpers.addsToTemplate.format(f"codeql/{self.language}-all", predicate, rows[i][key])
6366

6467
return extensions
6568

@@ -75,7 +78,7 @@ def makeContent(self):
7578
sources = self.getAddsTo("ExtractSources.ql", helpers.sourceModelPredicate)
7679
sinks = self.getAddsTo("ExtractSinks.ql", helpers.sinkModelPredicate)
7780
neutrals = self.getAddsTo("ExtractNeutrals.ql", helpers.neutralModelPredicate)
78-
return merge(sources, sinks, summaries, neutrals)
81+
return [merge(sources[0], sinks[0], summaries[0], neutrals[0]), merge(sources[1], sinks[1], summaries[1], neutrals[1])]
7982

8083

8184
def save(self, extensions):
@@ -85,9 +88,13 @@ def save(self, extensions):
8588
# Create a file for each namespace and save models.
8689
extensionTemplate = """extensions:
8790
{0}"""
88-
for entry in extensions:
91+
for entry in extensions[0]:
8992
with open(self.extDir + "/" + entry + self.modelFileExtension, "w") as f:
90-
f.write(extensionTemplate.format(extensions[entry]))
93+
f.write(extensionTemplate.format(extensions[0][entry]))
94+
95+
for entry in extensions[1]:
96+
with open(self.extDir + "/generated/" + entry + self.modelFileExtension, "w") as f:
97+
f.write(extensionTemplate.format(extensions[1][entry]))
9198

9299
def run(self):
93100
extensions = self.makeContent()

0 commit comments

Comments
 (0)