Python: routing tests 3-7 and some annotations

This commit is contained in:
Rasmus Lerchedahl Petersen
2020-11-12 23:07:01 +01:00
parent 4fe2576b9a
commit e468d49b19
3 changed files with 189 additions and 8 deletions

View File

@@ -74,12 +74,12 @@ def argument_passing(
):
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:89 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:94 -> ControlFlowNode for a"
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:94 -> ControlFlowNode for b" MISSING:arg2="ControlFlowNode for arg2, l:89 -> ControlFlowNode for b"
SINK3(c)
SINK4(d)
SINK5(e)
SINK6(f)
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:94 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:89 -> ControlFlowNode for c"
SINK4(d) #$ MISSING: arg4="ControlFlowNode for arg4, l:89 -> ControlFlowNode for d"
SINK5(e) #$ MISSING: arg5="ControlFlowNode for arg5, l:89 -> ControlFlowNode for e"
SINK6(f) #$ MISSING: arg6="ControlFlowNode for arg6, l:89 -> ControlFlowNode for f"
try:
SINK7(g["g"])
SINK7(g["g"]) #$ arg7="ControlFlowNode for arg7, l:89 -> ControlFlowNode for Subscript"
except:
print("OK")
@@ -109,7 +109,7 @@ def test_pos_only():
def with_multiple_kw_args(a, b, c):
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:117 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:118 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:119 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:120 -> ControlFlowNode for a"
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:117 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:120 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:118 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:119 -> ControlFlowNode for b"
SINK3(c)
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:117 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:119 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:120 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:118 -> ControlFlowNode for c"
@expects(9)
@@ -123,7 +123,7 @@ def test_multiple_kw_args():
def with_default_arguments(a=arg1, b=arg2, c=arg3):
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:132 -> ControlFlowNode for a" MISSING:arg1="ControlFlowNode for arg1, l:123 -> ControlFlowNode for a"
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:133 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:123 -> ControlFlowNode for b"
SINK3(c)
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:134 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:123 -> ControlFlowNode for c"
@expects(12)
@@ -152,7 +152,7 @@ def grab_bar_baz(bar, **kwargs):
def grab_baz(baz):
SINK3(baz)
SINK3(baz) #$ arg3="ControlFlowNode for arg3, l:160 -> ControlFlowNode for baz"
@expects(4)

View File

@@ -1,5 +1,6 @@
| classes.py:556:15:556:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" |
| classes.py:557:15:557:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" |
| classes.py:571:15:571:19 | ControlFlowNode for value | Unexpected result: arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value" |
| classes.py:572:15:572:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" |
| classes.py:573:15:573:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" |
| classes.py:587:15:587:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" |

View File

@@ -81,3 +81,183 @@ class Argument2RoutingConfig extends DataFlow::Configuration {
*/
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
class Argument3RoutingTest extends FlowTest {
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 FlowTest {
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 FlowTest {
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 FlowTest {
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 FlowTest {
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) }
}