Skip to content

Commit 90db9b3

Browse files
committed
C#: Add MaD source and sink test query to shared library.
1 parent 4177c38 commit 90db9b3

File tree

4 files changed

+90
-14
lines changed

4 files changed

+90
-14
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,14 +395,14 @@ Declaration interpretElement(
395395
* A callable where there exists a MaD sink model that applies to it.
396396
*/
397397
class SinkCallable extends Callable {
398-
SinkCallable() { SourceSinkInterpretationInput::sinkElement(this, _, _) }
398+
SinkCallable() { SourceSinkInterpretationInput::sinkElement(this, _, _, _) }
399399
}
400400

401401
/**
402402
* A callable where there exists a MaD source model that applies to it.
403403
*/
404404
class SourceCallable extends Callable {
405-
SourceCallable() { SourceSinkInterpretationInput::sourceElement(this, _, _) }
405+
SourceCallable() { SourceSinkInterpretationInput::sourceElement(this, _, _, _) }
406406
}
407407

408408
cached

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,20 +160,20 @@ module SourceSinkInterpretationInput implements
160160

161161
class Element = Cs::Element;
162162

163-
predicate sourceElement(Element e, string output, string kind) {
163+
predicate sourceElement(Element e, string output, string kind, Public::Provenance provenance) {
164164
exists(
165165
string namespace, string type, boolean subtypes, string name, string signature, string ext
166166
|
167-
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, _) and
167+
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
168168
e = interpretElement(namespace, type, subtypes, name, signature, ext)
169169
)
170170
}
171171

172-
predicate sinkElement(Element e, string input, string kind) {
172+
predicate sinkElement(Element e, string input, string kind, Public::Provenance provenance) {
173173
exists(
174174
string namespace, string type, boolean subtypes, string name, string signature, string ext
175175
|
176-
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, _) and
176+
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance) and
177177
e = interpretElement(namespace, type, subtypes, name, signature, ext)
178178
)
179179
}

csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import shared.FlowSummaries
22
import semmle.code.csharp.dataflow.internal.ExternalFlow
3+
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl::Private::External
34

45
private class IncludeAllSummarizedCallable extends IncludeSummarizedCallable {
56
IncludeAllSummarizedCallable() { exists(this) }
@@ -9,3 +10,19 @@ private class IncludeNeutralSummarizedCallable extends RelevantNeutralCallable {
910
/** Gets a string representing the callable in semi-colon separated format for use in flow summaries. */
1011
final override string getCallableCsv() { result = asPartialNeutralModel(this) }
1112
}
13+
14+
module TestSourceSinkInput implements TestSourceSinkInputSig {
15+
class RelevantSourceCallable instanceof SourceCallable {
16+
string getCallableCsv() { result = asPartialModel(this) }
17+
18+
string toString() { result = super.toString() }
19+
}
20+
21+
class RelevantSinkCallable instanceof SinkCallable {
22+
string getCallableCsv() { result = asPartialModel(this) }
23+
24+
string toString() { result = super.toString() }
25+
}
26+
}
27+
28+
import TestSourceSinkOutput<TestSourceSinkInput>

shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,13 +1468,13 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
14681468
* Holds if an external source specification exists for `n` with output specification
14691469
* `output` and kind `kind`.
14701470
*/
1471-
predicate sourceElement(Element n, string output, string kind);
1471+
predicate sourceElement(Element n, string output, string kind, Provenance provenance);
14721472

14731473
/**
14741474
* Holds if an external sink specification exists for `n` with input specification
14751475
* `input` and kind `kind`.
14761476
*/
1477-
predicate sinkElement(Element n, string input, string kind);
1477+
predicate sinkElement(Element n, string input, string kind, Provenance provenance);
14781478

14791479
class SourceOrSinkElement extends Element;
14801480

@@ -1529,8 +1529,8 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
15291529
private import SourceSinkInterpretationInput
15301530

15311531
private predicate sourceSinkSpec(string spec) {
1532-
sourceElement(_, spec, _) or
1533-
sinkElement(_, spec, _)
1532+
sourceElement(_, spec, _, _) or
1533+
sinkElement(_, spec, _, _)
15341534
}
15351535

15361536
private module AccessPath = AccessPathSyntax::AccessPath<sourceSinkSpec/1>;
@@ -1562,7 +1562,7 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
15621562
InterpretNode ref, SourceSinkAccessPath output, string kind
15631563
) {
15641564
exists(SourceOrSinkElement e |
1565-
sourceElement(e, output, kind) and
1565+
sourceElement(e, output, kind, _) and
15661566
if outputNeedsReferenceExt(output.getToken(0))
15671567
then e = ref.getCallTarget()
15681568
else e = ref.asElement()
@@ -1576,7 +1576,7 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
15761576

15771577
private predicate sinkElementRef(InterpretNode ref, SourceSinkAccessPath input, string kind) {
15781578
exists(SourceOrSinkElement e |
1579-
sinkElement(e, input, kind) and
1579+
sinkElement(e, input, kind, _) and
15801580
if inputNeedsReferenceExt(input.getToken(0))
15811581
then e = ref.getCallTarget()
15821582
else e = ref.asElement()
@@ -1691,6 +1691,63 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
16911691
interpretInput(input, input.getNumToken(), ref, node)
16921692
)
16931693
}
1694+
1695+
signature module TestSourceSinkInputSig {
1696+
/**
1697+
* A class or source elements relevant for testing.
1698+
*/
1699+
class RelevantSourceCallable instanceof SourceOrSinkElement {
1700+
/** Gets the string representation of this callable used by `source/1`. */
1701+
string getCallableCsv();
1702+
}
1703+
1704+
/**
1705+
* A class or sink elements relevant for testing.
1706+
*/
1707+
class RelevantSinkCallable instanceof SourceOrSinkElement {
1708+
/** Gets the string representation of this callable used by `source/1`. */
1709+
string getCallableCsv();
1710+
}
1711+
}
1712+
1713+
/** Provides query predicates for outputting a set of relevant sources and sinks. */
1714+
module TestSourceSinkOutput<TestSourceSinkInputSig TestSourceSinkInput> {
1715+
private import TestSourceSinkInput
1716+
1717+
/**
1718+
* Holds if there exists a relevant source callable with information roughly corresponding to `csv`.
1719+
* Used for testing.
1720+
* The syntax is: "namespace;type;overrides;name;signature;ext;outputspec;kind;provenance",
1721+
* ext is hardcoded to empty.
1722+
*/
1723+
query predicate source(string csv) {
1724+
exists(RelevantSourceCallable c, string output, string kind, Provenance provenance |
1725+
sourceElement(c, output, kind, provenance) and
1726+
csv =
1727+
c.getCallableCsv() // Callable information
1728+
+ output + ";" // output
1729+
+ kind + ";" // kind
1730+
+ provenance // provenance
1731+
)
1732+
}
1733+
1734+
/**
1735+
* Holds if there exists a relevant sink callable with information roughly corresponding to `csv`.
1736+
* Used for testing.
1737+
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;kind;provenance",
1738+
* ext is hardcoded to empty.
1739+
*/
1740+
query predicate sink(string csv) {
1741+
exists(RelevantSinkCallable c, string input, string kind, Provenance provenance |
1742+
sinkElement(c, input, kind, provenance) and
1743+
csv =
1744+
c.getCallableCsv() // Callable information
1745+
+ input + ";" // input
1746+
+ kind + ";" // kind
1747+
+ provenance // provenance
1748+
)
1749+
}
1750+
}
16941751
}
16951752
}
16961753

@@ -1746,7 +1803,8 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
17461803
}
17471804

17481805
/**
1749-
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
1806+
* Holds if there exists a relevant summary callable with information roughly corresponding to `csv`.
1807+
* Used for testing.
17501808
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance",
17511809
* ext is hardcoded to empty.
17521810
*/
@@ -1766,7 +1824,8 @@ module Make<DF::InputSig DataFlowLang, InputSig<DataFlowLang> Input> {
17661824
}
17671825

17681826
/**
1769-
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
1827+
* Holds if there exists a relevant neutral callable with information roughly corresponding to `csv`.
1828+
* Used for testing.
17701829
* The syntax is: "namespace;type;name;signature;kind;provenance"",
17711830
*/
17721831
query predicate neutral(string csv) {

0 commit comments

Comments
 (0)