Python: Update more inline expectation tests to use the paramterized module

This commit is contained in:
Jeroen Ketema
2023-06-15 16:44:04 +02:00
parent c53e529bac
commit dba4460526
153 changed files with 551 additions and 379 deletions

View File

@@ -3,12 +3,10 @@ import semmle.python.dataflow.new.DataFlow
import TestUtilities.InlineExpectationsTest
private import semmle.python.dataflow.new.internal.PrintNode
class DataFlowQueryTest extends InlineExpectationsTest {
DataFlowQueryTest() { this = "DataFlowQueryTest" }
module DataFlowQueryTest implements TestSig {
string getARelevantTag() { result = "result" }
override string getARelevantTag() { result = "result" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Configuration cfg, DataFlow::Node sink | cfg.hasFlowTo(sink) |
location = sink.getLocation() and
tag = "result" and
@@ -22,7 +20,7 @@ class DataFlowQueryTest extends InlineExpectationsTest {
// Sometimes a line contains both an alert and a safe sink.
// In this situation, the annotation form `OK(safe sink)`
// can be useful.
override predicate hasOptionalResult(Location location, string element, string tag, string value) {
predicate hasOptionalResult(Location location, string element, string tag, string value) {
exists(DataFlow::Configuration cfg, DataFlow::Node sink |
cfg.isSink(sink) or cfg.isSink(sink, _)
|
@@ -34,6 +32,8 @@ class DataFlowQueryTest extends InlineExpectationsTest {
}
}
import MakeTest<DataFlowQueryTest>
query predicate missingAnnotationOnSink(Location location, string error, string element) {
error = "ERROR, you should add `# $ MISSING: result=BAD` or `result=OK` annotation" and
exists(DataFlow::Node sink |
@@ -42,13 +42,13 @@ query predicate missingAnnotationOnSink(Location location, string error, string
location = sink.getLocation() and
element = prettyExpr(sink.asExpr()) and
not exists(DataFlow::Configuration cfg | cfg.hasFlowTo(sink)) and
not exists(FalseNegativeExpectation missingResult |
not exists(FalseNegativeTestExpectation missingResult |
missingResult.getTag() = "result" and
missingResult.getValue() = "BAD" and
missingResult.getLocation().getFile() = location.getFile() and
missingResult.getLocation().getStartLine() = location.getStartLine()
) and
not exists(GoodExpectation okResult |
not exists(GoodTestExpectation okResult |
okResult.getTag() = "result" and
okResult.getValue() in ["OK", "OK(" + prettyNode(sink) + ")"] and
okResult.getLocation().getFile() = location.getFile() and

View File

@@ -3,22 +3,21 @@ import semmle.python.dataflow.new.DataFlow
import TestUtilities.InlineExpectationsTest
private import semmle.python.dataflow.new.internal.PrintNode
abstract class FlowTest extends InlineExpectationsTest {
bindingset[this]
FlowTest() { any() }
signature module FlowTestSig {
string flowTag();
abstract string flowTag();
predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode);
}
abstract predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode);
private module FlowTest<FlowTestSig Impl> implements TestSig {
string getARelevantTag() { result = Impl::flowTag() }
override string getARelevantTag() { result = this.flowTag() }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node fromNode, DataFlow::Node toNode | this.relevantFlow(fromNode, toNode) |
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node fromNode, DataFlow::Node toNode | Impl::relevantFlow(fromNode, toNode) |
location = toNode.getLocation() and
tag = this.flowTag() and
tag = Impl::flowTag() and
value =
"\"" + prettyNode(fromNode).replaceAll("\"", "'") + this.lineStr(fromNode, toNode) + " -> " +
"\"" + prettyNode(fromNode).replaceAll("\"", "'") + lineStr(fromNode, toNode) + " -> " +
prettyNode(toNode).replaceAll("\"", "'") + "\"" and
element = toNode.toString()
)
@@ -38,3 +37,11 @@ abstract class FlowTest extends InlineExpectationsTest {
)
}
}
module MakeFlowTest<FlowTestSig Impl> {
import MakeTest<FlowTest<Impl>>
}
module MakeFlowTest2<FlowTestSig Impl1, FlowTestSig Impl2> {
import MakeTest<MergeTests<FlowTest<Impl1>, FlowTest<Impl2>>>
}

View File

@@ -2,12 +2,12 @@ import python
import semmle.python.dataflow.new.DataFlow
import FlowTest
class LocalFlowStepTest extends FlowTest {
LocalFlowStepTest() { this = "LocalFlowStepTest" }
module LocalFlowStepTest implements FlowTestSig {
string flowTag() { result = "step" }
override string flowTag() { result = "step" }
override predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode) {
predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode) {
DataFlow::localFlowStep(fromNode, toNode)
}
}
import MakeFlowTest<LocalFlowStepTest>

View File

@@ -3,25 +3,23 @@ import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate
import FlowTest
class MaximalFlowTest extends FlowTest {
MaximalFlowTest() { this = "MaximalFlowTest" }
module MaximalFlowTest implements FlowTestSig {
string flowTag() { result = "flow" }
override string flowTag() { result = "flow" }
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
source != sink and
exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink))
MaximalFlows::flow(source, sink)
}
}
import MakeFlowTest<MaximalFlowTest>
/**
* A configuration to find all "maximal" flows.
* To be used on small programs.
*/
class MaximalFlowsConfig extends DataFlow::Configuration {
MaximalFlowsConfig() { this = "MaximalFlowsConfig" }
override predicate isSource(DataFlow::Node node) {
module MaximalFlowsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
exists(node.getLocation().getFile().getRelativePath()) and
not node.asCfgNode() instanceof CallNode and
not node.asCfgNode().getNode() instanceof Return and
@@ -32,7 +30,7 @@ class MaximalFlowsConfig extends DataFlow::Configuration {
not DataFlow::localFlowStep(_, node)
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
exists(node.getLocation().getFile().getRelativePath()) and
not any(CallNode c).getArg(_) = node.asCfgNode() and
not node instanceof DataFlow::ArgumentNode and
@@ -40,3 +38,5 @@ class MaximalFlowsConfig extends DataFlow::Configuration {
not DataFlow::localFlowStep(node, _)
}
}
module MaximalFlows = DataFlow::Global<MaximalFlowsConfig>;

View File

@@ -3,20 +3,20 @@ import experimental.dataflow.TestUtil.FlowTest
import experimental.dataflow.testConfig
private import semmle.python.dataflow.new.internal.PrintNode
class DataFlowTest extends FlowTest {
DataFlowTest() { this = "DataFlowTest" }
module DataFlowTest implements FlowTestSig {
string flowTag() { result = "flow" }
override string flowTag() { result = "flow" }
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
TestFlow::flow(source, sink)
}
}
import MakeFlowTest<DataFlowTest>
query predicate missingAnnotationOnSink(Location location, string error, string element) {
error = "ERROR, you should add `# $ MISSING: flow` annotation" and
exists(DataFlow::Node sink |
any(TestConfiguration config).isSink(sink) and
TestConfig::isSink(sink) and
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
exists(DataFlow::CallCfgNode call |
call.getFunction().asCfgNode().(NameNode).getId() = "SINK" and
@@ -24,8 +24,8 @@ query predicate missingAnnotationOnSink(Location location, string error, string
) and
location = sink.getLocation() and
element = prettyExpr(sink.asExpr()) and
not any(TestConfiguration config).hasFlow(_, sink) and
not exists(FalseNegativeExpectation missingResult |
not TestFlow::flowTo(sink) and
not exists(FalseNegativeTestExpectation missingResult |
missingResult.getTag() = "flow" and
missingResult.getLocation().getFile() = location.getFile() and
missingResult.getLocation().getStartLine() = location.getStartLine()

View File

@@ -3,16 +3,16 @@ import experimental.dataflow.TestUtil.FlowTest
import experimental.dataflow.testTaintConfig
private import semmle.python.dataflow.new.internal.PrintNode
class DataFlowTest extends FlowTest {
DataFlowTest() { this = "DataFlowTest" }
module DataFlowTest implements FlowTestSig {
string flowTag() { result = "flow" }
override string flowTag() { result = "flow" }
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
TestFlow::flow(source, sink)
}
}
import MakeFlowTest<DataFlowTest>
query predicate missingAnnotationOnSink(Location location, string error, string element) {
error = "ERROR, you should add `# $ MISSING: flow` annotation" and
exists(DataFlow::Node sink |
@@ -23,8 +23,8 @@ query predicate missingAnnotationOnSink(Location location, string error, string
) and
location = sink.getLocation() and
element = prettyExpr(sink.asExpr()) and
not any(TestConfiguration config).hasFlow(_, sink) and
not exists(FalseNegativeExpectation missingResult |
not TestFlow::flowTo(sink) and
not exists(FalseNegativeTestExpectation missingResult |
missingResult.getTag() = "flow" and
missingResult.getLocation().getFile() = location.getFile() and
missingResult.getLocation().getStartLine() = location.getStartLine()

View File

@@ -4,11 +4,11 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPr
private import semmle.python.ApiGraphs
import TestUtilities.InlineExpectationsTest
class UnresolvedCallExpectations extends InlineExpectationsTest {
UnresolvedCallExpectations() { this = "UnresolvedCallExpectations" }
override string getARelevantTag() { result = "unresolved_call" }
signature module UnresolvedCallExpectationsSig {
predicate unresolvedCall(CallNode call);
}
module DefaultUnresolvedCallExpectations implements UnresolvedCallExpectationsSig {
predicate unresolvedCall(CallNode call) {
not exists(DataFlowPrivate::DataFlowCall dfc |
exists(dfc.getCallable()) and dfc.getNode() = call
@@ -16,14 +16,22 @@ class UnresolvedCallExpectations extends InlineExpectationsTest {
not DataFlowPrivate::resolveClassCall(call, _) and
not call = API::builtin(_).getACall().asCfgNode()
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(CallNode call | this.unresolvedCall(call) |
location = call.getLocation() and
tag = "unresolved_call" and
value = prettyExpr(call.getNode()) and
element = call.toString()
)
}
}
module MakeUnresolvedCallExpectations<UnresolvedCallExpectationsSig Impl> {
private module UnresolvedCallExpectations implements TestSig {
string getARelevantTag() { result = "unresolved_call" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(CallNode call | Impl::unresolvedCall(call) |
location = call.getLocation() and
tag = "unresolved_call" and
value = prettyExpr(call.getNode()) and
element = call.toString()
)
}
}
import MakeTest<UnresolvedCallExpectations>
}

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -1,2 +1,3 @@
missingAnnotationOnSink
failures
testFailures

View File

@@ -1,2 +1,3 @@
missingAnnotationOnSink
failures
testFailures

View File

@@ -1,2 +1,3 @@
missingAnnotationOnSink
failures
testFailures

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -2,11 +2,13 @@ import python
import experimental.dataflow.TestUtil.UnresolvedCalls
private import semmle.python.dataflow.new.DataFlow
class IgnoreDictMethod extends UnresolvedCallExpectations {
override predicate unresolvedCall(CallNode call) {
super.unresolvedCall(call) and
module IgnoreDictMethod implements UnresolvedCallExpectationsSig {
predicate unresolvedCall(CallNode call) {
DefaultUnresolvedCallExpectations::unresolvedCall(call) and
not any(DataFlow::MethodCallNode methodCall |
methodCall.getMethodName() in ["get", "setdefault"]
).asCfgNode() = call
}
}
import MakeUnresolvedCallExpectations<IgnoreDictMethod>

View File

@@ -1,2 +1,3 @@
missingAnnotationOnSink
failures
testFailures

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -4,12 +4,10 @@ import experimental.dataflow.TestUtil.FlowTest
private import semmle.python.dataflow.new.internal.PrintNode
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DP
class ImportTimeLocalFlowTest extends FlowTest {
ImportTimeLocalFlowTest() { this = "ImportTimeLocalFlowTest" }
module ImportTimeLocalFlowTest implements FlowTestSig {
string flowTag() { result = "importTimeFlow" }
override string flowTag() { result = "importTimeFlow" }
override predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and
// results are displayed next to `nodeTo`, so we need a line to write on
nodeTo.getLocation().getStartLine() > 0 and
@@ -18,12 +16,10 @@ class ImportTimeLocalFlowTest extends FlowTest {
}
}
class RuntimeLocalFlowTest extends FlowTest {
RuntimeLocalFlowTest() { this = "RuntimeLocalFlowTest" }
module RuntimeLocalFlowTest implements FlowTestSig {
string flowTag() { result = "runtimeFlow" }
override string flowTag() { result = "runtimeFlow" }
override predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
predicate relevantFlow(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
nodeFrom.getLocation().getFile().getBaseName() = "multiphase.py" and
// results are displayed next to `nodeTo`, so we need a line to write on
nodeTo.getLocation().getStartLine() > 0 and
@@ -34,3 +30,5 @@ class RuntimeLocalFlowTest extends FlowTest {
DP::runtimeJumpStep(nodeFrom, nodeTo)
}
}
import MakeFlowTest2<ImportTimeLocalFlowTest, RuntimeLocalFlowTest>

View File

@@ -9,5 +9,5 @@ import python
import experimental.dataflow.testConfig
from DataFlow::Node source, DataFlow::Node sink
where exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
where TestFlow::flow(source, sink)
select source, sink

View File

@@ -1,2 +1,3 @@
missingAnnotationOnSink
failures
testFailures

View File

@@ -4,7 +4,7 @@
import python
import semmle.python.dataflow.new.FlowSummary
import DataFlow::PathGraph
import TestFlow::PathGraph
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.internal.FlowSummaryImpl
import semmle.python.ApiGraphs
@@ -16,6 +16,6 @@ query predicate invalidSpecComponent(SummarizedCallable sc, string s, string c)
Private::External::invalidSpecComponent(s, c)
}
from DataFlow::PathNode source, DataFlow::PathNode sink, TestConfiguration conf
where conf.hasFlowPath(source, sink)
from TestFlow::PathNode source, TestFlow::PathNode sink
where TestFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,3 +1,4 @@
failures
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures
testFailures

View File

@@ -1,6 +1,12 @@
import experimental.meta.InlineTaintTest
import semmle.python.dataflow.new.BarrierGuards
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof StringConstCompareBarrier }
module CustomSanitizerOverridesConfig implements DataFlow::ConfigSig {
predicate isSource = TestTaintTrackingConfig::isSource/1;
predicate isSink = TestTaintTrackingConfig::isSink/1;
predicate isBarrier(DataFlow::Node node) { node instanceof StringConstCompareBarrier }
}
import MakeInlineTaintTest<CustomSanitizerOverridesConfig>

View File

@@ -1,25 +1,26 @@
failures
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures
testFailures
isSanitizer
| TestTaintTrackingConfiguration | test.py:21:39:21:39 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:34:39:34:39 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:52:28:52:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:66:10:66:29 | ControlFlowNode for emulated_escaping() |
| TestTaintTrackingConfiguration | test_logical.py:33:28:33:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:40:28:40:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:48:28:48:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:53:28:53:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:92:28:92:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:103:28:103:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:111:28:111:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:130:28:130:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:137:28:137:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:148:28:148:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:151:28:151:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:158:28:158:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:167:24:167:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:176:24:176:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:185:24:185:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:193:24:193:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_reference.py:31:28:31:28 | ControlFlowNode for s |
| test.py:21:39:21:39 | ControlFlowNode for s |
| test.py:34:39:34:39 | ControlFlowNode for s |
| test.py:52:28:52:28 | ControlFlowNode for s |
| test.py:66:10:66:29 | ControlFlowNode for emulated_escaping() |
| test_logical.py:33:28:33:28 | ControlFlowNode for s |
| test_logical.py:40:28:40:28 | ControlFlowNode for s |
| test_logical.py:48:28:48:28 | ControlFlowNode for s |
| test_logical.py:53:28:53:28 | ControlFlowNode for s |
| test_logical.py:92:28:92:28 | ControlFlowNode for s |
| test_logical.py:103:28:103:28 | ControlFlowNode for s |
| test_logical.py:111:28:111:28 | ControlFlowNode for s |
| test_logical.py:130:28:130:28 | ControlFlowNode for s |
| test_logical.py:137:28:137:28 | ControlFlowNode for s |
| test_logical.py:148:28:148:28 | ControlFlowNode for s |
| test_logical.py:151:28:151:28 | ControlFlowNode for s |
| test_logical.py:158:28:158:28 | ControlFlowNode for s |
| test_logical.py:167:24:167:24 | ControlFlowNode for s |
| test_logical.py:176:24:176:24 | ControlFlowNode for s |
| test_logical.py:185:24:185:24 | ControlFlowNode for s |
| test_logical.py:193:24:193:24 | ControlFlowNode for s |
| test_reference.py:31:28:31:28 | ControlFlowNode for s |

View File

@@ -12,8 +12,12 @@ predicate isUnsafeCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean bra
branch = false
}
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
override predicate isSanitizer(DataFlow::Node node) {
module CustomSanitizerOverridesConfig implements DataFlow::ConfigSig {
predicate isSource = TestTaintTrackingConfig::isSource/1;
predicate isSink = TestTaintTrackingConfig::isSink/1;
predicate isBarrier(DataFlow::Node node) {
exists(Call call |
call.getFunc().(Name).getId() = "emulated_authentication_check" and
call.getArg(0) = node.asExpr()
@@ -27,7 +31,9 @@ class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
}
}
query predicate isSanitizer(TestTaintTrackingConfiguration conf, DataFlow::Node node) {
import MakeInlineTaintTest<CustomSanitizerOverridesConfig>
query predicate isSanitizer(DataFlow::Node node) {
exists(node.getLocation().getFile().getRelativePath()) and
conf.isSanitizer(node)
CustomSanitizerOverridesConfig::isBarrier(node)
}

View File

@@ -1,3 +1,4 @@
failures
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures
testFailures

View File

@@ -1 +1,2 @@
import experimental.meta.InlineTaintTest
import MakeInlineTaintTest<TestTaintTrackingConfig>

View File

@@ -1,3 +1,4 @@
failures
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures
testFailures

View File

@@ -1 +1,2 @@
import experimental.meta.InlineTaintTest
import MakeInlineTaintTest<TestTaintTrackingConfig>

View File

@@ -1,3 +1,4 @@
failures
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures
testFailures

View File

@@ -1 +1,2 @@
import experimental.meta.InlineTaintTest
import MakeInlineTaintTest<TestTaintTrackingConfig>

View File

@@ -1,2 +1,3 @@
missingAnnotationOnSink
failures
testFailures

View File

@@ -1,3 +1,4 @@
failures
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures
testFailures

View File

@@ -1 +1,2 @@
import experimental.meta.InlineTaintTest
import MakeInlineTaintTest<TestTaintTrackingConfig>

View File

@@ -23,10 +23,8 @@
private import python
import semmle.python.dataflow.new.DataFlow
class TestConfiguration extends DataFlow::Configuration {
TestConfiguration() { this = "TestConfiguration" }
override predicate isSource(DataFlow::Node node) {
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
or
node.(DataFlow::CfgNode).getNode().getNode().(StrConst).getS() = "source"
@@ -37,7 +35,7 @@ class TestConfiguration extends DataFlow::Configuration {
// No support for complex numbers
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
exists(DataFlow::CallCfgNode call |
call.getFunction().asCfgNode().(NameNode).getId() in ["SINK", "SINK_F"] and
(node = call.getArg(_) or node = call.getArgByName(_)) and
@@ -45,5 +43,7 @@ class TestConfiguration extends DataFlow::Configuration {
)
}
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
module TestFlow = DataFlow::Global<TestConfig>;

View File

@@ -24,10 +24,8 @@ private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
class TestConfiguration extends TaintTracking::Configuration {
TestConfiguration() { this = "TestConfiguration" }
override predicate isSource(DataFlow::Node node) {
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
or
node.(DataFlow::CfgNode).getNode().getNode().(StrConst).getS() = "source"
@@ -38,12 +36,14 @@ class TestConfiguration extends TaintTracking::Configuration {
// No support for complex numbers
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
exists(CallNode call |
call.getFunction().(NameNode).getId() in ["SINK", "SINK_F"] and
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
override predicate isSanitizerIn(DataFlow::Node node) { this.isSource(node) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
module TestFlow = TaintTracking::Global<TestConfig>;

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -14,12 +14,10 @@ private DataFlow::TypeTrackingNode tracked(TypeTracker t) {
exists(TypeTracker t2 | result = tracked(t2).track(t2, t))
}
class TrackedTest extends InlineExpectationsTest {
TrackedTest() { this = "TrackedTest" }
module TrackedTest implements TestSig {
string getARelevantTag() { result = "tracked" }
override string getARelevantTag() { result = "tracked" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node e, TypeTracker t |
tracked(t).flowsTo(e) and
// Module variables have no sensible location, and hence can't be annotated.
@@ -54,12 +52,10 @@ private DataFlow::TypeTrackingNode string_type(TypeTracker t) {
exists(TypeTracker t2 | result = string_type(t2).track(t2, t))
}
class TrackedIntTest extends InlineExpectationsTest {
TrackedIntTest() { this = "TrackedIntTest" }
module TrackedIntTest implements TestSig {
string getARelevantTag() { result = "int" }
override string getARelevantTag() { result = "int" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node e, TypeTracker t |
int_type(t).flowsTo(e) and
tag = "int" and
@@ -70,12 +66,10 @@ class TrackedIntTest extends InlineExpectationsTest {
}
}
class TrackedStringTest extends InlineExpectationsTest {
TrackedStringTest() { this = "TrackedStringTest" }
module TrackedStringTest implements TestSig {
string getARelevantTag() { result = "str" }
override string getARelevantTag() { result = "str" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node e, TypeTracker t |
string_type(t).flowsTo(e) and
tag = "str" and
@@ -100,12 +94,10 @@ private DataFlow::TypeTrackingNode tracked_self(TypeTracker t) {
exists(TypeTracker t2 | result = tracked_self(t2).track(t2, t))
}
class TrackedSelfTest extends InlineExpectationsTest {
TrackedSelfTest() { this = "TrackedSelfTest" }
module TrackedSelfTest implements TestSig {
string getARelevantTag() { result = "tracked_self" }
override string getARelevantTag() { result = "tracked_self" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node e, TypeTracker t |
tracked_self(t).flowsTo(e) and
// Module variables have no sensible location, and hence can't be annotated.
@@ -161,12 +153,10 @@ private DataFlow::TypeTrackingNode foo_bar_baz(DataFlow::TypeTracker t) {
/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
DataFlow::Node foo_bar_baz() { foo_bar_baz(DataFlow::TypeTracker::end()).flowsTo(result) }
class TrackedFooBarBaz extends InlineExpectationsTest {
TrackedFooBarBaz() { this = "TrackedFooBarBaz" }
module TrackedFooBarBaz implements TestSig {
string getARelevantTag() { result = "tracked_foo_bar_baz" }
override string getARelevantTag() { result = "tracked_foo_bar_baz" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node e |
e = foo_bar_baz() and
// Module variables have no sensible location, and hence can't be annotated.
@@ -178,3 +168,5 @@ class TrackedFooBarBaz extends InlineExpectationsTest {
)
}
}
import MakeTest<MergeTests5<TrackedTest, TrackedIntTest, TrackedStringTest, TrackedSelfTest, TrackedFooBarBaz>>

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -7,7 +7,7 @@ module CaptureTest implements TestSig {
string getARelevantTag() { result = "captured" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node sink | exists(TestConfiguration cfg | cfg.hasFlowTo(sink)) |
exists(DataFlow::Node sink | TestFlow::flowTo(sink) |
location = sink.getLocation() and
tag = "captured" and
value = "" and