mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Python: Refactor argumentRoutingTest.ql to be more generic
I checked to see that the tests still works. If I deleted the `arg5`
annotation, it got failures:
```diff
diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py
index e218bdde9b..71816c1e01 100644
--- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py
+++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py
@@ -46,7 +46,7 @@ def argument_passing(
c,
d=arg4, #$ arg4 func=argument_passing
*,
- e=arg5, #$ arg5 func=argument_passing
+ e=arg5,
f,
**g,
):
diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected
index e69de29bb2..22037a40c3 100644
--- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected
+++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected
@@ -0,0 +1,2 @@
+| argumentPassing.py:49:7:49:10 | ControlFlowNode for arg5 | Unexpected result: arg5= |
+| argumentPassing.py:49:7:49:10 | ControlFlowNode for arg5 | Unexpected result: func=argument_passing |
```
This commit is contained in:
@@ -46,29 +46,48 @@ class Argument1RoutingConfig extends DataFlow::Configuration {
|
||||
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument2RoutingTest extends RoutingTest {
|
||||
Argument2RoutingTest() { this = "Argument2RoutingTest" }
|
||||
// for argument 2 and up, we use a generic approach. Change `maxNumArgs` below if we
|
||||
// need to increase the maximum number of arguments.
|
||||
private int maxNumArgs() { result = 7 }
|
||||
|
||||
override string flowTag() { result = "arg2" }
|
||||
class RestArgumentRoutingTest extends RoutingTest {
|
||||
int argNumber;
|
||||
|
||||
RestArgumentRoutingTest() {
|
||||
argNumber in [2 .. maxNumArgs()] and
|
||||
this = "Argument" + argNumber + "RoutingTest"
|
||||
}
|
||||
|
||||
override string flowTag() { result = "arg" + argNumber }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument2RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
exists(RestArgumentRoutingConfig cfg | cfg.getArgNumber() = argNumber |
|
||||
cfg.hasFlow(source, sink)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument2RoutingConfig extends DataFlow::Configuration {
|
||||
Argument2RoutingConfig() { this = "Argument2RoutingConfig" }
|
||||
class RestArgumentRoutingConfig extends DataFlow::Configuration {
|
||||
int argNumber;
|
||||
|
||||
RestArgumentRoutingConfig() {
|
||||
argNumber in [2 .. maxNumArgs()] and
|
||||
this = "Argument" + argNumber + "RoutingConfig"
|
||||
}
|
||||
|
||||
/** Gets the argument number this configuration is for. */
|
||||
int getArgNumber() { result = argNumber }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg2"
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg" + argNumber
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK2" and
|
||||
call.getFunction().(NameNode).getId() = "SINK" + argNumber and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
@@ -79,185 +98,5 @@ class Argument2RoutingConfig 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) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument3RoutingTest extends RoutingTest {
|
||||
Argument3RoutingTest() { this = "Argument3RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg3" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument3RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument3RoutingConfig extends DataFlow::Configuration {
|
||||
Argument3RoutingConfig() { this = "Argument3RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg3"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK3" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* 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) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument4RoutingTest extends RoutingTest {
|
||||
Argument4RoutingTest() { this = "Argument4RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg4" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument4RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument4RoutingConfig extends DataFlow::Configuration {
|
||||
Argument4RoutingConfig() { this = "Argument4RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg4"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK4" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* 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) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument5RoutingTest extends RoutingTest {
|
||||
Argument5RoutingTest() { this = "Argument5RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg5" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument5RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument5RoutingConfig extends DataFlow::Configuration {
|
||||
Argument5RoutingConfig() { this = "Argument5RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg5"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK5" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* 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) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument6RoutingTest extends RoutingTest {
|
||||
Argument6RoutingTest() { this = "Argument6RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg6" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument6RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument6RoutingConfig extends DataFlow::Configuration {
|
||||
Argument6RoutingConfig() { this = "Argument6RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg6"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK6" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* 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) { isSource(node) }
|
||||
}
|
||||
|
||||
class Argument7RoutingTest extends RoutingTest {
|
||||
Argument7RoutingTest() { this = "Argument7RoutingTest" }
|
||||
|
||||
override string flowTag() { result = "arg7" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(Argument7RoutingConfig cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to check routing of arguments through magic methods.
|
||||
*/
|
||||
class Argument7RoutingConfig extends DataFlow::Configuration {
|
||||
Argument7RoutingConfig() { this = "Argument7RoutingConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg7"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK7" and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
|
||||
* Use-use flow lets the argument to the first call reach the sink inside the second call,
|
||||
* 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) { isSource(node) }
|
||||
override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user