Python: Update rest of tests to new dataflow lib

I had missed these originally, since I had just fixed the ones that were
highlighted in the actions logs, thinking they had covered everything :(
This commit is contained in:
Rasmus Wriedt Larsen
2023-12-04 14:48:47 +01:00
parent 46531e653d
commit c952f6a648
18 changed files with 109 additions and 133 deletions

View File

@@ -16,15 +16,13 @@ private import semmle.python.dataflow.new.RemoteFlowSources
private import meta.MetaMetrics
private import semmle.python.dataflow.new.internal.PrintNode
class RemoteFlowSourceReach extends TaintTracking::Configuration {
RemoteFlowSourceReach() { this = "RemoteFlowSourceReach" }
override predicate isSource(DataFlow::Node node) {
module RemoteFlowSourceReachConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node instanceof RemoteFlowSource and
not node.getLocation().getFile() instanceof IgnoredFile
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
not node.getLocation().getFile() instanceof IgnoredFile
// We could try to reduce the number of sinks in this configuration, by only
// allowing something that is on one end of a localFlowStep, readStep or storeStep,
@@ -37,6 +35,8 @@ class RemoteFlowSourceReach extends TaintTracking::Configuration {
}
}
from RemoteFlowSourceReach cfg, DataFlow::Node reachable
where cfg.hasFlow(_, reachable)
module RemoteFlowSourceReachFlow = TaintTracking::Global<RemoteFlowSourceReachConfig>;
from DataFlow::Node reachable
where RemoteFlowSourceReachFlow::flow(_, reachable)
select reachable, prettyNode(reachable)

View File

@@ -104,9 +104,9 @@ module FromTaintTrackingStateConfig<DataFlow::StateConfigSig C> {
import MakeQueryTest<Impl>
}
signature class LegacyConfiguration extends DataFlow::Configuration;
deprecated signature class LegacyConfiguration extends DataFlow::Configuration;
module FromLegacyConfiguration<LegacyConfiguration C> {
deprecated module FromLegacyConfiguration<LegacyConfiguration C> {
module Impl implements QueryTestSig {
predicate isSink(DataFlow::Node sink) { any(C c).isSink(sink) or any(C c).isSink(sink, _) }

View File

@@ -4,10 +4,10 @@ import semmle.python.dataflow.new.DataFlow
* A configuration to find all flows.
* To be used on tiny programs.
*/
class AllFlowsConfig extends DataFlow::Configuration {
AllFlowsConfig() { this = "AllFlowsConfig" }
module AllFlowsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { any() }
override predicate isSource(DataFlow::Node node) { any() }
override predicate isSink(DataFlow::Node node) { any() }
predicate isSink(DataFlow::Node node) { any() }
}
module AllFlowsFlow = DataFlow::Global<AllFlowsConfig>;

View File

@@ -3,7 +3,7 @@ import allFlowsConfig
from DataFlow::Node source, DataFlow::Node sink
where
source != sink and
exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink)) and
AllFlowsFlow::flow(source, sink) and
exists(source.getLocation().getFile().getRelativePath()) and
exists(sink.getLocation().getFile().getRelativePath())
select source, sink

View File

@@ -1,6 +1,6 @@
import allFlowsConfig
from DataFlow::PathNode fromNode, DataFlow::PathNode toNode
from AllFlowsFlow::PathNode fromNode, AllFlowsFlow::PathNode toNode
where
toNode = fromNode.getASuccessor() and
exists(fromNode.getNode().getLocation().getFile().getRelativePath()) and

View File

@@ -3,7 +3,7 @@ import maximalFlowsConfig
from DataFlow::Node source, DataFlow::Node sink
where
source != sink and
exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink)) and
MaximalFlowsFlow::flow(source, sink) and
exists(source.getLocation().getFile().getRelativePath()) and
exists(sink.getLocation().getFile().getRelativePath())
select source, sink

View File

@@ -5,20 +5,20 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPr
* A configuration to find all "maximal" flows.
* To be used on small programs.
*/
class MaximalFlowsConfig extends DataFlow::Configuration {
MaximalFlowsConfig() { this = "AllFlowsConfig" }
override predicate isSource(DataFlow::Node node) {
module MaximalFlowsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node instanceof DataFlow::ParameterNode
or
node instanceof DataFlow::EssaNode and
not exists(DataFlow::EssaNode pred | DataFlow::localFlowStep(pred, node))
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
node instanceof DataFlowPrivate::ReturnNode
or
node instanceof DataFlow::EssaNode and
not exists(node.(DataFlow::EssaNode).getVar().getASourceUse())
}
}
module MaximalFlowsFlow = DataFlow::Global<MaximalFlowsConfig>;

View File

@@ -2,6 +2,6 @@ import allFlowsConfig
from DataFlow::Node sink
where
exists(AllFlowsConfig cfg | cfg.isSink(sink)) and
AllFlowsConfig::isSink(sink) and
exists(sink.getLocation().getFile().getRelativePath())
select sink

View File

@@ -2,6 +2,6 @@ import allFlowsConfig
from DataFlow::Node source
where
exists(AllFlowsConfig cfg | cfg.isSource(source)) and
AllFlowsConfig::isSource(source) and
exists(source.getLocation().getFile().getRelativePath())
select source

View File

@@ -10,13 +10,11 @@ module Argument1RoutingTest implements RoutingTestSig {
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink, Argument arg) {
(
exists(Argument1ExtraRoutingConfig cfg | cfg.hasFlow(source, sink))
Argument1ExtraRoutingFlow::flow(source, sink)
or
exists(ArgumentRoutingConfig cfg |
cfg.hasFlow(source, sink) and
cfg.isArgSource(source, 1) and
cfg.isGoodSink(sink, 1)
)
ArgumentRoutingFlow::flow(source, sink) and
ArgumentRoutingConfig::isArgSource(source, 1) and
ArgumentRoutingConfig::isGoodSink(sink, 1)
) and
exists(arg)
}
@@ -26,32 +24,28 @@ class ArgNumber extends int {
ArgNumber() { this in [1 .. 7] }
}
class ArgumentRoutingConfig extends DataFlow::Configuration {
ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" }
predicate isArgSource(DataFlow::Node node, ArgNumber argNumber) {
module ArgumentRoutingConfig implements DataFlow::ConfigSig {
additional predicate isArgSource(DataFlow::Node node, ArgNumber argNumber) {
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg" + argNumber
}
override predicate isSource(DataFlow::Node node) { this.isArgSource(node, _) }
predicate isSource(DataFlow::Node node) { isArgSource(node, _) }
predicate isGoodSink(DataFlow::Node node, ArgNumber argNumber) {
additional predicate isGoodSink(DataFlow::Node node, ArgNumber argNumber) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK" + argNumber and
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
predicate isBadSink(DataFlow::Node node, ArgNumber argNumber) {
additional predicate isBadSink(DataFlow::Node node, ArgNumber argNumber) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK" + argNumber + "_F" and
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
override predicate isSink(DataFlow::Node node) {
this.isGoodSink(node, _) or this.isBadSink(node, _)
}
predicate isSink(DataFlow::Node node) { isGoodSink(node, _) or isBadSink(node, _) }
/**
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
@@ -59,13 +53,13 @@ class ArgumentRoutingConfig extends DataFlow::Configuration {
* making it seem like we handle all cases even if we only handle the last one.
* We make the test honest by preventing flow into source nodes.
*/
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
class Argument1ExtraRoutingConfig extends DataFlow::Configuration {
Argument1ExtraRoutingConfig() { this = "Argument1ExtraRoutingConfig" }
module ArgumentRoutingFlow = DataFlow::Global<ArgumentRoutingConfig>;
override predicate isSource(DataFlow::Node node) {
module Argument1ExtraRoutingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
exists(AssignmentDefinition def, DataFlow::CallCfgNode call |
def.getVariable() = node.(DataFlow::EssaNode).getVar() and
def.getValue() = call.getNode() and
@@ -74,7 +68,7 @@ class Argument1ExtraRoutingConfig extends DataFlow::Configuration {
node.(DataFlow::EssaNode).getVar().getName().matches("with\\_%")
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK1" and
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
@@ -87,20 +81,20 @@ class Argument1ExtraRoutingConfig extends DataFlow::Configuration {
* making it seem like we handle all cases even if we only handle the last one.
* We make the test honest by preventing flow into source nodes.
*/
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
module Argument1ExtraRoutingFlow = DataFlow::Global<Argument1ExtraRoutingConfig>;
module RestArgumentRoutingTest implements RoutingTestSig {
class Argument = ArgNumber;
string flowTag(Argument arg) { result = "arg" + arg }
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink, Argument arg) {
exists(ArgumentRoutingConfig cfg |
cfg.hasFlow(source, sink) and
cfg.isArgSource(source, arg) and
cfg.isGoodSink(sink, arg)
) and
ArgumentRoutingFlow::flow(source, sink) and
ArgumentRoutingConfig::isArgSource(source, arg) and
ArgumentRoutingConfig::isGoodSink(sink, arg) and
arg > 1
}
}
@@ -112,11 +106,9 @@ module BadArgumentRoutingTestSinkF implements RoutingTestSig {
string flowTag(Argument arg) { result = "bad" + arg }
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink, Argument arg) {
exists(ArgumentRoutingConfig cfg |
cfg.hasFlow(source, sink) and
cfg.isArgSource(source, arg) and
cfg.isBadSink(sink, arg)
)
ArgumentRoutingFlow::flow(source, sink) and
ArgumentRoutingConfig::isArgSource(source, arg) and
ArgumentRoutingConfig::isBadSink(sink, arg)
}
}
@@ -127,14 +119,12 @@ module BadArgumentRoutingTestWrongSink implements RoutingTestSig {
string flowTag(Argument arg) { result = "bad" + arg }
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink, Argument arg) {
exists(ArgumentRoutingConfig cfg |
cfg.hasFlow(source, sink) and
cfg.isArgSource(source, any(ArgNumber i | not i = arg)) and
(
cfg.isGoodSink(sink, arg)
or
cfg.isBadSink(sink, arg)
)
ArgumentRoutingFlow::flow(source, sink) and
ArgumentRoutingConfig::isArgSource(source, any(ArgNumber i | not i = arg)) and
(
ArgumentRoutingConfig::isGoodSink(sink, arg)
or
ArgumentRoutingConfig::isBadSink(sink, arg)
)
}
}

View File

@@ -4,16 +4,16 @@ import semmle.python.dataflow.new.DataFlow
* A configuration to find all flows.
* To be used on tiny programs.
*/
class AllFlowsConfig extends DataFlow::Configuration {
AllFlowsConfig() { this = "AllFlowsConfig" }
module AllFlowsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { any() }
override predicate isSource(DataFlow::Node node) { any() }
override predicate isSink(DataFlow::Node node) { any() }
predicate isSink(DataFlow::Node node) { any() }
}
module AllFlowsFlow = DataFlow::Global<AllFlowsConfig>;
from DataFlow::CfgNode source, DataFlow::CfgNode sink
where
source != sink and
exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink))
AllFlowsFlow::flow(source, sink)
select source, sink

View File

@@ -10,14 +10,10 @@
import python
import semmle.python.dataflow.new.DataFlow
class CustomTestConfiguration extends DataFlow::Configuration {
CustomTestConfiguration() { this = "CustomTestConfiguration" }
module CustomTestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.asCfgNode().(NameNode).getId() = "CUSTOM_SOURCE" }
override predicate isSource(DataFlow::Node node) {
node.asCfgNode().(NameNode).getId() = "CUSTOM_SOURCE"
}
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
exists(CallNode call |
call.getFunction().(NameNode).getId() in ["CUSTOM_SINK", "CUSTOM_SINK_F"] and
node.asCfgNode() = call.getAnArg()
@@ -25,6 +21,8 @@ class CustomTestConfiguration extends DataFlow::Configuration {
}
}
module CustomTestFlow = DataFlow::Global<CustomTestConfig>;
from DataFlow::Node source, DataFlow::Node sink
where exists(CustomTestConfiguration cfg | cfg.hasFlow(source, sink))
where CustomTestFlow::flow(source, sink)
select source, sink

View File

@@ -20,7 +20,7 @@ module SensitiveDataSourcesTest implements TestSig {
tag = "SensitiveDataSource"
or
exists(DataFlow::Node use |
any(SensitiveUseConfiguration config).hasFlow(source, use) and
SensitiveUseFlow::flow(source, use) and
location = use.getLocation() and
element = use.toString() and
value = source.getClassification() and
@@ -32,19 +32,17 @@ module SensitiveDataSourcesTest implements TestSig {
import MakeTest<SensitiveDataSourcesTest>
class SensitiveUseConfiguration extends TaintTracking::Configuration {
SensitiveUseConfiguration() { this = "SensitiveUseConfiguration" }
module SensitiveUseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof SensitiveDataSource }
override predicate isSource(DataFlow::Node node) { node instanceof SensitiveDataSource }
predicate isSink(DataFlow::Node node) { node = API::builtin("print").getACall().getArg(_) }
override predicate isSink(DataFlow::Node node) {
node = API::builtin("print").getACall().getArg(_)
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
sensitiveDataExtraStepForCalls(node1, node2)
}
}
module SensitiveUseFlow = TaintTracking::Global<SensitiveUseConfig>;
// import DataFlow::PathGraph
// from SensitiveUseConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
// where cfg.hasFlowPath(source, sink)

View File

@@ -3,10 +3,8 @@ import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.PrintNode
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
module TestTaintTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// Standard sources
source.(DataFlow::CfgNode).getNode().(NameNode).getId() in [
"TAINTED_STRING", "TAINTED_BYTES", "TAINTED_LIST", "TAINTED_DICT"
@@ -19,7 +17,7 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
)
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(CallNode call |
call.getFunction().(NameNode).getId() in ["ensure_tainted", "ensure_not_tainted"] and
sink.(DataFlow::CfgNode).getNode() = call.getAnArg()
@@ -27,6 +25,8 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
}
}
module TestTaintTrackingFlow = DataFlow::Global<TestTaintTrackingConfig>;
query predicate test_taint(string arg_location, string test_res, string scope_name, string repr) {
exists(Call call, Expr arg, boolean expected_taint, boolean has_taint |
// only consider files that are extracted as part of the test
@@ -42,9 +42,9 @@ query predicate test_taint(string arg_location, string test_res, string scope_na
(
// TODO: Replace with `hasFlowToExpr` once that is working
if
exists(TaintTracking::Configuration c |
c.hasFlowTo(any(DataFlow::Node n | n.(DataFlow::CfgNode).getNode() = arg.getAFlowNode()))
)
TestTaintTrackingFlow::flowTo(any(DataFlow::Node n |
n.(DataFlow::CfgNode).getNode() = arg.getAFlowNode()
))
then has_taint = true
else has_taint = false
) and

View File

@@ -2,14 +2,12 @@ import python
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
module TestTaintTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK" and
sink.(DataFlow::CfgNode).getNode() = call.getAnArg()
@@ -17,6 +15,8 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
}
}
from TestTaintTrackingConfiguration config, DataFlow::Node source, DataFlow::Node sink
where config.hasFlow(source, sink)
module TestTaintTrackingFlow = DataFlow::Global<TestTaintTrackingConfig>;
from DataFlow::Node source, DataFlow::Node sink
where TestTaintTrackingFlow::flow(source, sink)
select source, sink

View File

@@ -58,27 +58,27 @@ private class VersionGuardedNode extends DataFlow::Node {
int getVersion() { result = version }
}
private class ImportConfiguration extends DataFlow::Configuration {
ImportConfiguration() { this = "ImportConfiguration" }
module ImportConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof SourceString }
override predicate isSource(DataFlow::Node source) { source instanceof SourceString }
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
sink = API::moduleImport("trace").getMember("check").getACall().getArg(1)
}
override predicate isBarrier(DataFlow::Node node) {
predicate isBarrier(DataFlow::Node node) {
exists(DataFlow::MethodCallNode call | call.calls(node, "block_flow"))
}
}
module ImportFlow = DataFlow::Global<ImportConfig>;
module ResolutionTest implements TestSig {
string getARelevantTag() { result = "prints" }
predicate hasActualResult(Location location, string element, string tag, string value) {
(
exists(DataFlow::PathNode source, DataFlow::PathNode sink, ImportConfiguration config |
config.hasFlowPath(source, sink) and
exists(ImportFlow::PathNode source, ImportFlow::PathNode sink |
ImportFlow::flowPath(source, sink) and
not sink.getNode() instanceof VersionGuardedNode and
tag = "prints" and
location = sink.getNode().getLocation() and
@@ -108,8 +108,8 @@ module VersionSpecificResolutionTest implements TestSig {
predicate hasActualResult(Location location, string element, string tag, string value) {
(
exists(DataFlow::PathNode source, DataFlow::PathNode sink, ImportConfiguration config |
config.hasFlowPath(source, sink) and
exists(ImportFlow::PathNode source, ImportFlow::PathNode sink |
ImportFlow::flowPath(source, sink) and
tag = getTagForVersion(sink.getNode().(VersionGuardedNode).getVersion()) and
location = sink.getNode().getLocation() and
value = source.getNode().(SourceString).getContents() and

View File

@@ -10,26 +10,18 @@ predicate pointsToOrigin(DataFlow::CfgNode pointer, DataFlow::CfgNode origin) {
origin.getNode() = pointer.getNode().pointsTo().getOrigin()
}
class PointsToConfiguration extends DataFlow::Configuration {
PointsToConfiguration() { this = "PointsToConfiguration" }
module PointsToConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { pointsToOrigin(_, node) }
override predicate isSource(DataFlow::Node node) { pointsToOrigin(_, node) }
override predicate isSink(DataFlow::Node node) { pointsToOrigin(node, _) }
predicate isSink(DataFlow::Node node) { pointsToOrigin(node, _) }
}
predicate hasFlow(DataFlow::Node origin, DataFlow::Node pointer) {
exists(PointsToConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink |
source.getNode() = origin and
sink.getNode() = pointer and
config.hasFlowPath(source, sink)
)
}
module PointsToFlow = DataFlow::Global<PointsToConfig>;
from DataFlow::Node pointer, DataFlow::Node origin
where
exists(pointer.getLocation().getFile().getRelativePath()) and
exists(origin.getLocation().getFile().getRelativePath()) and
pointsToOrigin(pointer, origin) and
not hasFlow(origin, pointer)
not PointsToFlow::flow(origin, pointer)
select origin, pointer

View File

@@ -5,20 +5,18 @@ import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
class BasicTaintTracking extends TaintTracking::Configuration {
BasicTaintTracking() { this = "BasicTaintTracking" }
override predicate isSource(DataFlow::Node source) {
module BasicTaintTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = ModelOutput::getASourceNode("test-source").asSource()
}
override predicate isSink(DataFlow::Node sink) {
sink = ModelOutput::getASinkNode("test-sink").asSink()
}
predicate isSink(DataFlow::Node sink) { sink = ModelOutput::getASinkNode("test-sink").asSink() }
}
module TestTaintTrackingFlow = TaintTracking::Global<BasicTaintTrackingConfig>;
query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) {
any(BasicTaintTracking tr).hasFlow(source, sink)
TestTaintTrackingFlow::flow(source, sink)
}
query predicate isSink(DataFlow::Node node, string kind) {