Merge branch 'main' of github.com:github/codeql into MagicMethods

This commit is contained in:
Rasmus Lerchedahl Petersen
2020-08-26 17:42:44 +02:00
350 changed files with 20369 additions and 3049 deletions

View File

@@ -88,6 +88,8 @@ uniquePostUpdate
postIsInSameCallable
reverseRead
storeIsPostUpdate
| test.py:152:9:152:16 | ControlFlowNode for List | Store targets should be PostUpdateNodes. |
| test.py:153:9:153:24 | ControlFlowNode for Dict | Store targets should be PostUpdateNodes. |
argHasPostUpdate
| test.py:25:10:25:10 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:29:10:29:10 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |

View File

@@ -0,0 +1,30 @@
import experimental.dataflow.DataFlow
/**
* A configuration to check routing of arguments through magic methods.
*/
class ArgumentRoutingConfig extends DataFlow::Configuration {
ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" }
override predicate isSource(DataFlow::Node node) {
exists(AssignmentDefinition def |
def.getVariable() = node.(DataFlow::EssaNode).getVar() and
def.getValue().(DataFlow::DataFlowCall).getCallable().getName().matches("With\\_%")
) and
node.(DataFlow::EssaNode).getVar().getName().matches("with\\_%")
}
override predicate isSink(DataFlow::Node node) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK1" and
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
}
from DataFlow::Node source, DataFlow::Node sink
where
source.getLocation().getFile().getBaseName() = "classes.py" and
sink.getLocation().getFile().getBaseName() = "classes.py" and
exists(ArgumentRoutingConfig cfg | cfg.hasFlow(source, sink))
select source, sink

View File

@@ -0,0 +1,26 @@
import experimental.dataflow.DataFlow
/**
* A configuration to check routing of arguments through magic methods.
*/
class ArgumentRoutingConfig extends DataFlow::Configuration {
ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" }
override predicate isSource(DataFlow::Node node) {
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg2"
}
override predicate isSink(DataFlow::Node node) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK2" and
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
}
from DataFlow::Node source, DataFlow::Node sink
where
source.getLocation().getFile().getBaseName() = "classes.py" and
sink.getLocation().getFile().getBaseName() = "classes.py" and
exists(ArgumentRoutingConfig cfg | cfg.hasFlow(source, sink))
select source, sink

View File

@@ -0,0 +1,26 @@
import experimental.dataflow.DataFlow
/**
* A configuration to check routing of arguments through magic methods.
*/
class ArgumentRoutingConfig extends DataFlow::Configuration {
ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" }
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()
)
}
}
from DataFlow::Node source, DataFlow::Node sink
where
source.getLocation().getFile().getBaseName() = "classes.py" and
sink.getLocation().getFile().getBaseName() = "classes.py" and
exists(ArgumentRoutingConfig cfg | cfg.hasFlow(source, sink))
select source, sink

View File

@@ -0,0 +1,26 @@
import experimental.dataflow.DataFlow
/**
* A configuration to check routing of arguments through magic methods.
*/
class ArgumentRoutingConfig extends DataFlow::Configuration {
ArgumentRoutingConfig() { this = "ArgumentRoutingConfig" }
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()
)
}
}
from DataFlow::Node source, DataFlow::Node sink
where
source.getLocation().getFile().getBaseName() = "classes.py" and
sink.getLocation().getFile().getBaseName() = "classes.py" and
exists(ArgumentRoutingConfig cfg | cfg.hasFlow(source, sink))
select source, sink

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,39 @@
| classes.py:19:12:19:31 | ControlFlowNode for Attribute() | classes.py:19:12:19:31 | ControlFlowNode for Attribute() |
| classes.py:174:7:174:22 | ControlFlowNode for set() | classes.py:174:7:174:22 | ControlFlowNode for set() |
| classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() |
| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() |
| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() |
| classes.py:428:3:428:14 | ControlFlowNode for with_getitem | classes.py:422:19:422:22 | SSA variable self |
| classes.py:428:16:428:16 | ControlFlowNode for IntegerLiteral | classes.py:422:25:422:27 | SSA variable key |
| classes.py:438:3:438:14 | ControlFlowNode for with_setitem | classes.py:433:19:433:22 | SSA variable self |
| classes.py:438:16:438:16 | ControlFlowNode for IntegerLiteral | classes.py:433:25:433:27 | SSA variable key |
| classes.py:438:21:438:22 | ControlFlowNode for Str | classes.py:433:30:433:34 | SSA variable value |
| classes.py:448:7:448:18 | ControlFlowNode for with_delitem | classes.py:443:19:443:22 | SSA variable self |
| classes.py:448:20:448:20 | ControlFlowNode for IntegerLiteral | classes.py:443:25:443:27 | SSA variable key |
| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() |
| classes.py:505:3:505:10 | ControlFlowNode for with_add | classes.py:499:15:499:18 | SSA variable self |
| classes.py:505:14:505:21 | ControlFlowNode for with_add | classes.py:499:21:499:25 | SSA variable other |
| classes.py:516:3:516:10 | ControlFlowNode for with_sub | classes.py:510:15:510:18 | SSA variable self |
| classes.py:516:14:516:21 | ControlFlowNode for with_sub | classes.py:510:21:510:25 | SSA variable other |
| classes.py:527:3:527:10 | ControlFlowNode for with_mul | classes.py:521:15:521:18 | SSA variable self |
| classes.py:527:14:527:21 | ControlFlowNode for with_mul | classes.py:521:21:521:25 | SSA variable other |
| classes.py:538:3:538:13 | ControlFlowNode for with_matmul | classes.py:532:18:532:21 | SSA variable self |
| classes.py:538:17:538:27 | ControlFlowNode for with_matmul | classes.py:532:24:532:28 | SSA variable other |
| classes.py:549:3:549:14 | ControlFlowNode for with_truediv | classes.py:543:19:543:22 | SSA variable self |
| classes.py:549:18:549:29 | ControlFlowNode for with_truediv | classes.py:543:25:543:29 | SSA variable other |
| classes.py:560:3:560:15 | ControlFlowNode for with_floordiv | classes.py:554:20:554:23 | SSA variable self |
| classes.py:560:20:560:32 | ControlFlowNode for with_floordiv | classes.py:554:26:554:30 | SSA variable other |
| classes.py:571:3:571:10 | ControlFlowNode for with_mod | classes.py:565:15:565:18 | SSA variable self |
| classes.py:571:14:571:21 | ControlFlowNode for with_mod | classes.py:565:21:565:25 | SSA variable other |
| classes.py:597:3:597:10 | ControlFlowNode for with_pow | classes.py:587:15:587:18 | SSA variable self |
| classes.py:597:15:597:22 | ControlFlowNode for with_pow | classes.py:587:21:587:25 | SSA variable other |
| classes.py:608:3:608:13 | ControlFlowNode for with_lshift | classes.py:602:18:602:21 | SSA variable self |
| classes.py:608:18:608:28 | ControlFlowNode for with_lshift | classes.py:602:24:602:28 | SSA variable other |
| classes.py:619:3:619:13 | ControlFlowNode for with_rshift | classes.py:613:18:613:21 | SSA variable self |
| classes.py:619:18:619:28 | ControlFlowNode for with_rshift | classes.py:613:24:613:28 | SSA variable other |
| classes.py:630:3:630:10 | ControlFlowNode for with_and | classes.py:624:15:624:18 | SSA variable self |
| classes.py:630:14:630:21 | ControlFlowNode for with_and | classes.py:624:21:624:25 | SSA variable other |
| classes.py:641:3:641:10 | ControlFlowNode for with_xor | classes.py:635:15:635:18 | SSA variable self |
| classes.py:641:14:641:21 | ControlFlowNode for with_xor | classes.py:635:21:635:25 | SSA variable other |
| classes.py:652:3:652:9 | ControlFlowNode for with_or | classes.py:646:14:646:17 | SSA variable self |
| classes.py:652:13:652:19 | ControlFlowNode for with_or | classes.py:646:20:646:24 | SSA variable other |
| classes.py:41:16:41:35 | ControlFlowNode for Attribute() | classes.py:41:16:41:35 | ControlFlowNode for Attribute() |
| classes.py:264:9:264:24 | ControlFlowNode for set() | classes.py:264:9:264:24 | ControlFlowNode for set() |
| classes.py:269:9:269:30 | ControlFlowNode for frozenset() | classes.py:269:9:269:30 | ControlFlowNode for frozenset() |
| classes.py:274:9:274:28 | ControlFlowNode for dict() | classes.py:274:9:274:28 | ControlFlowNode for dict() |
| classes.py:454:29:454:52 | ControlFlowNode for dict() | classes.py:454:29:454:52 | ControlFlowNode for dict() |
| classes.py:622:5:622:16 | ControlFlowNode for with_getitem | classes.py:612:21:612:24 | SSA variable self |
| classes.py:622:18:622:21 | ControlFlowNode for arg2 | classes.py:612:27:612:29 | SSA variable key |
| classes.py:640:5:640:16 | ControlFlowNode for with_setitem | classes.py:629:21:629:24 | SSA variable self |
| classes.py:640:18:640:21 | ControlFlowNode for arg2 | classes.py:629:27:629:29 | SSA variable key |
| classes.py:640:26:640:29 | ControlFlowNode for arg3 | classes.py:629:32:629:36 | SSA variable value |
| classes.py:656:9:656:20 | ControlFlowNode for with_delitem | classes.py:647:21:647:24 | SSA variable self |
| classes.py:656:22:656:25 | ControlFlowNode for arg2 | classes.py:647:27:647:29 | SSA variable key |
| classes.py:683:16:683:28 | ControlFlowNode for Attribute() | classes.py:683:16:683:28 | ControlFlowNode for Attribute() |
| classes.py:737:5:737:12 | ControlFlowNode for with_add | classes.py:727:17:727:20 | SSA variable self |
| classes.py:737:16:737:19 | ControlFlowNode for arg2 | classes.py:727:23:727:27 | SSA variable other |
| classes.py:754:5:754:12 | ControlFlowNode for with_sub | classes.py:744:17:744:20 | SSA variable self |
| classes.py:754:16:754:19 | ControlFlowNode for arg2 | classes.py:744:23:744:27 | SSA variable other |
| classes.py:771:5:771:12 | ControlFlowNode for with_mul | classes.py:761:17:761:20 | SSA variable self |
| classes.py:771:16:771:19 | ControlFlowNode for arg2 | classes.py:761:23:761:27 | SSA variable other |
| classes.py:788:5:788:15 | ControlFlowNode for with_matmul | classes.py:778:20:778:23 | SSA variable self |
| classes.py:788:19:788:22 | ControlFlowNode for arg2 | classes.py:778:26:778:30 | SSA variable other |
| classes.py:805:5:805:16 | ControlFlowNode for with_truediv | classes.py:795:21:795:24 | SSA variable self |
| classes.py:805:20:805:23 | ControlFlowNode for arg2 | classes.py:795:27:795:31 | SSA variable other |
| classes.py:822:5:822:17 | ControlFlowNode for with_floordiv | classes.py:812:22:812:25 | SSA variable self |
| classes.py:822:22:822:25 | ControlFlowNode for arg2 | classes.py:812:28:812:32 | SSA variable other |
| classes.py:839:5:839:12 | ControlFlowNode for with_mod | classes.py:829:17:829:20 | SSA variable self |
| classes.py:839:16:839:19 | ControlFlowNode for arg2 | classes.py:829:23:829:27 | SSA variable other |
| classes.py:879:5:879:12 | ControlFlowNode for with_pow | classes.py:863:17:863:20 | SSA variable self |
| classes.py:879:17:879:20 | ControlFlowNode for arg2 | classes.py:863:23:863:27 | SSA variable other |
| classes.py:896:5:896:15 | ControlFlowNode for with_lshift | classes.py:886:20:886:23 | SSA variable self |
| classes.py:896:20:896:23 | ControlFlowNode for arg2 | classes.py:886:26:886:30 | SSA variable other |
| classes.py:913:5:913:15 | ControlFlowNode for with_rshift | classes.py:903:20:903:23 | SSA variable self |
| classes.py:913:20:913:23 | ControlFlowNode for arg2 | classes.py:903:26:903:30 | SSA variable other |
| classes.py:930:5:930:12 | ControlFlowNode for with_and | classes.py:920:17:920:20 | SSA variable self |
| classes.py:930:16:930:19 | ControlFlowNode for arg2 | classes.py:920:23:920:27 | SSA variable other |
| classes.py:947:5:947:12 | ControlFlowNode for with_xor | classes.py:937:17:937:20 | SSA variable self |
| classes.py:947:16:947:19 | ControlFlowNode for arg2 | classes.py:937:23:937:27 | SSA variable other |
| classes.py:964:5:964:11 | ControlFlowNode for with_or | classes.py:954:16:954:19 | SSA variable self |
| classes.py:964:15:964:18 | ControlFlowNode for arg2 | classes.py:954:22:954:26 | SSA variable other |

View File

@@ -1,4 +1,29 @@
import experimental.dataflow.callGraphConfig
import experimental.dataflow.DataFlow
/**
* A configuration to find the call graph edges.
*/
class CallGraphConfig extends DataFlow::Configuration {
CallGraphConfig() { this = "CallGraphConfig" }
override predicate isSource(DataFlow::Node node) {
node instanceof DataFlow::ReturnNode
or
// These sources should allow for the non-standard call syntax
node instanceof DataFlow::ArgumentNode
}
override predicate isSink(DataFlow::Node node) {
node instanceof DataFlow::OutNode
or
node instanceof DataFlow::ParameterNode and
// exclude parameters to the SINK-functions
not exists(DataFlow::DataFlowCallable c |
node.(DataFlow::ParameterNode).isParameterOf(c, _) and
c.getName().matches("SINK_")
)
}
}
from DataFlow::Node source, DataFlow::Node sink
where
@@ -8,3 +33,4 @@ where
select source, sink
// Ideally, we would just have 1-step paths either from argument to parameter
// or from return to call. This gives a bit more, so should be rewritten.
// We should also consider splitting this into two, one for each direction.

View File

@@ -68,15 +68,69 @@ edges
| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| test.py:32:10:32:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:33:9:33:9 | ControlFlowNode for x [Tuple element at index 1] |
| test.py:32:21:32:26 | ControlFlowNode for SOURCE | test.py:32:10:32:26 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:33:9:33:9 | ControlFlowNode for x [Tuple element at index 1] | test.py:33:9:33:12 | ControlFlowNode for Subscript |
| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:34:10:34:10 | ControlFlowNode for y |
| test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x |
| test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x |
| test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x |
| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x |
| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x |
| test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x |
| test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() |
| test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() |
| test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() |
| test.py:74:9:74:16 | ControlFlowNode for List [List element] | test.py:75:10:75:10 | ControlFlowNode for x [List element] |
| test.py:74:10:74:15 | ControlFlowNode for SOURCE | test.py:74:9:74:16 | ControlFlowNode for List [List element] |
| test.py:75:10:75:10 | ControlFlowNode for x [List element] | test.py:75:10:75:13 | ControlFlowNode for Subscript |
| test.py:82:9:82:37 | ControlFlowNode for ListComp [List element] | test.py:83:10:83:10 | ControlFlowNode for x [List element] |
| test.py:82:10:82:15 | ControlFlowNode for SOURCE | test.py:82:9:82:37 | ControlFlowNode for ListComp [List element] |
| test.py:83:10:83:10 | ControlFlowNode for x [List element] | test.py:83:10:83:13 | ControlFlowNode for Subscript |
| test.py:86:9:86:29 | ControlFlowNode for ListComp [List element] | test.py:87:10:87:10 | ControlFlowNode for x [List element] |
| test.py:86:10:86:10 | ControlFlowNode for y | test.py:86:9:86:29 | ControlFlowNode for ListComp [List element] |
| test.py:86:16:86:16 | SSA variable y | test.py:86:10:86:10 | ControlFlowNode for y |
| test.py:86:21:86:28 | ControlFlowNode for List [List element] | test.py:86:16:86:16 | SSA variable y |
| test.py:86:22:86:27 | ControlFlowNode for SOURCE | test.py:86:21:86:28 | ControlFlowNode for List [List element] |
| test.py:87:10:87:10 | ControlFlowNode for x [List element] | test.py:87:10:87:13 | ControlFlowNode for Subscript |
| test.py:90:9:90:16 | ControlFlowNode for List [List element] | test.py:91:21:91:21 | ControlFlowNode for l [List element] |
| test.py:90:10:90:15 | ControlFlowNode for SOURCE | test.py:90:9:90:16 | ControlFlowNode for List [List element] |
| test.py:91:9:91:22 | ControlFlowNode for ListComp [List element] | test.py:92:10:92:10 | ControlFlowNode for x [List element] |
| test.py:91:10:91:10 | ControlFlowNode for y | test.py:91:9:91:22 | ControlFlowNode for ListComp [List element] |
| test.py:91:16:91:16 | SSA variable y | test.py:91:10:91:10 | ControlFlowNode for y |
| test.py:91:21:91:21 | ControlFlowNode for l [List element] | test.py:91:16:91:16 | SSA variable y |
| test.py:92:10:92:10 | ControlFlowNode for x [List element] | test.py:92:10:92:13 | ControlFlowNode for Subscript |
| test.py:100:9:100:16 | ControlFlowNode for Set [List element] | test.py:101:10:101:10 | ControlFlowNode for x [List element] |
| test.py:100:10:100:15 | ControlFlowNode for SOURCE | test.py:100:9:100:16 | ControlFlowNode for Set [List element] |
| test.py:101:10:101:10 | ControlFlowNode for x [List element] | test.py:101:10:101:16 | ControlFlowNode for Attribute() |
| test.py:104:9:104:37 | ControlFlowNode for SetComp [Set element] | test.py:105:10:105:10 | ControlFlowNode for x [Set element] |
| test.py:104:10:104:15 | ControlFlowNode for SOURCE | test.py:104:9:104:37 | ControlFlowNode for SetComp [Set element] |
| test.py:105:10:105:10 | ControlFlowNode for x [Set element] | test.py:105:10:105:16 | ControlFlowNode for Attribute() |
| test.py:108:9:108:29 | ControlFlowNode for SetComp [Set element] | test.py:109:10:109:10 | ControlFlowNode for x [Set element] |
| test.py:108:10:108:10 | ControlFlowNode for y | test.py:108:9:108:29 | ControlFlowNode for SetComp [Set element] |
| test.py:108:16:108:16 | SSA variable y | test.py:108:10:108:10 | ControlFlowNode for y |
| test.py:108:21:108:28 | ControlFlowNode for List [List element] | test.py:108:16:108:16 | SSA variable y |
| test.py:108:22:108:27 | ControlFlowNode for SOURCE | test.py:108:21:108:28 | ControlFlowNode for List [List element] |
| test.py:109:10:109:10 | ControlFlowNode for x [Set element] | test.py:109:10:109:16 | ControlFlowNode for Attribute() |
| test.py:112:9:112:16 | ControlFlowNode for Set [List element] | test.py:113:21:113:21 | ControlFlowNode for l [List element] |
| test.py:112:10:112:15 | ControlFlowNode for SOURCE | test.py:112:9:112:16 | ControlFlowNode for Set [List element] |
| test.py:113:9:113:22 | ControlFlowNode for SetComp [Set element] | test.py:114:10:114:10 | ControlFlowNode for x [Set element] |
| test.py:113:10:113:10 | ControlFlowNode for y | test.py:113:9:113:22 | ControlFlowNode for SetComp [Set element] |
| test.py:113:16:113:16 | SSA variable y | test.py:113:10:113:10 | ControlFlowNode for y |
| test.py:113:21:113:21 | ControlFlowNode for l [List element] | test.py:113:16:113:16 | SSA variable y |
| test.py:114:10:114:10 | ControlFlowNode for x [Set element] | test.py:114:10:114:16 | ControlFlowNode for Attribute() |
| test.py:122:9:122:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:123:10:123:10 | ControlFlowNode for x [Dictionary element at key s] |
| test.py:122:15:122:20 | ControlFlowNode for SOURCE | test.py:122:9:122:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:123:10:123:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:123:10:123:15 | ControlFlowNode for Subscript |
| test.py:126:9:126:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:127:10:127:10 | ControlFlowNode for x [Dictionary element at key s] |
| test.py:126:15:126:20 | ControlFlowNode for SOURCE | test.py:126:9:126:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:127:10:127:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:127:10:127:19 | ControlFlowNode for Attribute() |
| test.py:252:11:252:16 | ControlFlowNode for SOURCE | test.py:252:11:252:17 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:252:11:252:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:252:10:252:21 | ControlFlowNode for Subscript |
| test.py:255:10:255:17 | ControlFlowNode for List [List element] | test.py:255:10:255:20 | ControlFlowNode for Subscript |
| test.py:255:11:255:16 | ControlFlowNode for SOURCE | test.py:255:10:255:17 | ControlFlowNode for List [List element] |
| test.py:258:10:258:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:258:10:258:26 | ControlFlowNode for Subscript |
| test.py:258:15:258:20 | ControlFlowNode for SOURCE | test.py:258:10:258:21 | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:276:28:276:33 | ControlFlowNode for SOURCE | test.py:276:10:276:34 | ControlFlowNode for second() |
| test.py:335:12:335:17 | ControlFlowNode for SOURCE | test.py:335:10:335:18 | ControlFlowNode for f() |
| test.py:339:28:339:33 | ControlFlowNode for SOURCE | test.py:339:10:339:34 | ControlFlowNode for second() |
nodes
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
@@ -120,6 +174,11 @@ nodes
| datamodel.py:107:18:107:31 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| test.py:32:10:32:26 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:32:21:32:26 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:33:9:33:9 | ControlFlowNode for x [Tuple element at index 1] | semmle.label | ControlFlowNode for x [Tuple element at index 1] |
| test.py:33:9:33:12 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:34:10:34:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:43:9:43:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:44:10:44:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:48:9:48:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
@@ -132,12 +191,75 @@ nodes
| test.py:61:10:61:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:69:10:69:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:70:10:70:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:246:10:246:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:246:28:246:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:305:10:305:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| test.py:305:12:305:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:309:10:309:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:309:28:309:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:74:9:74:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:74:10:74:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:75:10:75:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:75:10:75:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:82:9:82:37 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:82:10:82:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:83:10:83:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:83:10:83:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:86:9:86:29 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:86:10:86:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:86:16:86:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:86:21:86:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:86:22:86:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:87:10:87:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:87:10:87:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:90:9:90:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:90:10:90:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:91:9:91:22 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] |
| test.py:91:10:91:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:91:16:91:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:91:21:91:21 | ControlFlowNode for l [List element] | semmle.label | ControlFlowNode for l [List element] |
| test.py:92:10:92:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:92:10:92:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:100:9:100:16 | ControlFlowNode for Set [List element] | semmle.label | ControlFlowNode for Set [List element] |
| test.py:100:10:100:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:101:10:101:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
| test.py:101:10:101:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:104:9:104:37 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:104:10:104:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:105:10:105:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:105:10:105:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:108:9:108:29 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:108:10:108:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:108:16:108:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:108:21:108:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:108:22:108:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:109:10:109:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:109:10:109:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:112:9:112:16 | ControlFlowNode for Set [List element] | semmle.label | ControlFlowNode for Set [List element] |
| test.py:112:10:112:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:113:9:113:22 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] |
| test.py:113:10:113:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:113:16:113:16 | SSA variable y | semmle.label | SSA variable y |
| test.py:113:21:113:21 | ControlFlowNode for l [List element] | semmle.label | ControlFlowNode for l [List element] |
| test.py:114:10:114:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] |
| test.py:114:10:114:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:122:9:122:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:122:15:122:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:123:10:123:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] |
| test.py:123:10:123:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:126:9:126:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:126:15:126:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:127:10:127:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] |
| test.py:127:10:127:19 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:252:10:252:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:252:11:252:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:252:11:252:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:255:10:255:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:255:10:255:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:255:11:255:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:258:10:258:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] |
| test.py:258:10:258:26 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test.py:258:15:258:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:276:10:276:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:276:28:276:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:335:10:335:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| test.py:335:12:335:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:339:10:339:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:339:28:339:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
#select
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | <message> |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | <message> |
@@ -156,12 +278,26 @@ nodes
| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | <message> |
| test.py:34:10:34:10 | ControlFlowNode for y | test.py:32:21:32:26 | ControlFlowNode for SOURCE | test.py:34:10:34:10 | ControlFlowNode for y | <message> |
| test.py:44:10:44:10 | ControlFlowNode for x | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | <message> |
| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | <message> |
| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | <message> |
| test.py:57:10:57:10 | ControlFlowNode for x | test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | <message> |
| test.py:61:10:61:10 | ControlFlowNode for x | test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | <message> |
| test.py:70:10:70:10 | ControlFlowNode for x | test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | <message> |
| test.py:246:10:246:34 | ControlFlowNode for second() | test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() | <message> |
| test.py:305:10:305:18 | ControlFlowNode for f() | test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | <message> |
| test.py:309:10:309:34 | ControlFlowNode for second() | test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | <message> |
| test.py:75:10:75:13 | ControlFlowNode for Subscript | test.py:74:10:74:15 | ControlFlowNode for SOURCE | test.py:75:10:75:13 | ControlFlowNode for Subscript | <message> |
| test.py:83:10:83:13 | ControlFlowNode for Subscript | test.py:82:10:82:15 | ControlFlowNode for SOURCE | test.py:83:10:83:13 | ControlFlowNode for Subscript | <message> |
| test.py:87:10:87:13 | ControlFlowNode for Subscript | test.py:86:22:86:27 | ControlFlowNode for SOURCE | test.py:87:10:87:13 | ControlFlowNode for Subscript | <message> |
| test.py:92:10:92:13 | ControlFlowNode for Subscript | test.py:90:10:90:15 | ControlFlowNode for SOURCE | test.py:92:10:92:13 | ControlFlowNode for Subscript | <message> |
| test.py:101:10:101:16 | ControlFlowNode for Attribute() | test.py:100:10:100:15 | ControlFlowNode for SOURCE | test.py:101:10:101:16 | ControlFlowNode for Attribute() | <message> |
| test.py:105:10:105:16 | ControlFlowNode for Attribute() | test.py:104:10:104:15 | ControlFlowNode for SOURCE | test.py:105:10:105:16 | ControlFlowNode for Attribute() | <message> |
| test.py:109:10:109:16 | ControlFlowNode for Attribute() | test.py:108:22:108:27 | ControlFlowNode for SOURCE | test.py:109:10:109:16 | ControlFlowNode for Attribute() | <message> |
| test.py:114:10:114:16 | ControlFlowNode for Attribute() | test.py:112:10:112:15 | ControlFlowNode for SOURCE | test.py:114:10:114:16 | ControlFlowNode for Attribute() | <message> |
| test.py:123:10:123:15 | ControlFlowNode for Subscript | test.py:122:15:122:20 | ControlFlowNode for SOURCE | test.py:123:10:123:15 | ControlFlowNode for Subscript | <message> |
| test.py:127:10:127:19 | ControlFlowNode for Attribute() | test.py:126:15:126:20 | ControlFlowNode for SOURCE | test.py:127:10:127:19 | ControlFlowNode for Attribute() | <message> |
| test.py:252:10:252:21 | ControlFlowNode for Subscript | test.py:252:11:252:16 | ControlFlowNode for SOURCE | test.py:252:10:252:21 | ControlFlowNode for Subscript | <message> |
| test.py:255:10:255:20 | ControlFlowNode for Subscript | test.py:255:11:255:16 | ControlFlowNode for SOURCE | test.py:255:10:255:20 | ControlFlowNode for Subscript | <message> |
| test.py:258:10:258:26 | ControlFlowNode for Subscript | test.py:258:15:258:20 | ControlFlowNode for SOURCE | test.py:258:10:258:26 | ControlFlowNode for Subscript | <message> |
| test.py:276:10:276:34 | ControlFlowNode for second() | test.py:276:28:276:33 | ControlFlowNode for SOURCE | test.py:276:10:276:34 | ControlFlowNode for second() | <message> |
| test.py:335:10:335:18 | ControlFlowNode for f() | test.py:335:12:335:17 | ControlFlowNode for SOURCE | test.py:335:10:335:18 | ControlFlowNode for f() | <message> |
| test.py:339:10:339:34 | ControlFlowNode for second() | test.py:339:28:339:33 | ControlFlowNode for SOURCE | test.py:339:10:339:34 | ControlFlowNode for second() | <message> |

View File

@@ -31,7 +31,7 @@ def SINK_F(x):
def test_tuple_with_local_flow():
x = (NONSOURCE, SOURCE)
y = x[1]
SINK(y) # Flow missing
SINK(y)
def test_tuple_negative():
x = (NONSOURCE, SOURCE)
@@ -72,7 +72,7 @@ def test_parenthesized_form():
# 6.2.5. List displays
def test_list_display():
x = [SOURCE]
SINK(x[0]) # Flow missing
SINK(x[0])
def test_list_display_negative():
x = [SOURCE]
@@ -80,7 +80,16 @@ def test_list_display_negative():
def test_list_comprehension():
x = [SOURCE for y in [NONSOURCE]]
SINK(x[0]) # Flow missing
SINK(x[0])
def test_list_comprehension_flow():
x = [y for y in [SOURCE]]
SINK(x[0])
def test_list_comprehension_inflow():
l = [SOURCE]
x = [y for y in l]
SINK(x[0])
def test_nested_list_display():
x = [* [SOURCE]]
@@ -89,11 +98,20 @@ def test_nested_list_display():
# 6.2.6. Set displays
def test_set_display():
x = {SOURCE}
SINK(x.pop()) # Flow missing
SINK(x.pop())
def test_set_comprehension():
x = {SOURCE for y in [NONSOURCE]}
SINK(x.pop()) # Flow missing
SINK(x.pop())
def test_set_comprehension_flow():
x = {y for y in [SOURCE]}
SINK(x.pop())
def test_set_comprehension_inflow():
l = {SOURCE}
x = {y for y in l}
SINK(x.pop())
def test_nested_set_display():
x = {* {SOURCE}}
@@ -102,16 +120,28 @@ def test_nested_set_display():
# 6.2.7. Dictionary displays
def test_dict_display():
x = {"s": SOURCE}
SINK(x["s"]) # Flow missing
SINK(x["s"])
def test_dict_display_pop():
x = {"s": SOURCE}
SINK(x.pop("s"))
def test_dict_comprehension():
x = {y: SOURCE for y in ["s"]}
SINK(x["s"]) # Flow missing
def test_dict_comprehension_pop():
x = {y: SOURCE for y in ["s"]}
SINK(x.pop("s")) # Flow missing
def test_nested_dict_display():
x = {** {"s": SOURCE}}
SINK(x["s"]) # Flow missing
def test_nested_dict_display_pop():
x = {** {"s": SOURCE}}
SINK(x.pop("s")) # Flow missing
# 6.2.8. Generator expressions
def test_generator():
x = (SOURCE for y in [NONSOURCE])
@@ -219,13 +249,13 @@ def test_attribute_reference():
# 6.3.2. Subscriptions
def test_subscription_tuple():
SINK((SOURCE,)[0]) # Flow missing
SINK((SOURCE,)[0])
def test_subscription_list():
SINK([SOURCE][0]) # Flow missing
SINK([SOURCE][0])
def test_subscription_mapping():
SINK({"s":SOURCE}["s"]) # Flow missing
SINK({"s":SOURCE}["s"])
# overriding __getitem__ should be tested by the class coverage tests

View File

@@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=1

View File

@@ -0,0 +1,72 @@
import python
import experimental.dataflow.TaintTracking
import experimental.dataflow.DataFlow
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
source.(DataFlow::CfgNode).getNode().(NameNode).getId() in ["TAINTED_STRING", "TAINTED_BYTES"]
}
override 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()
)
}
}
private string repr(Expr e) {
not e instanceof Num and
not e instanceof StrConst and
not e instanceof Subscript and
not e instanceof Call and
not e instanceof Attribute and
result = e.toString()
or
result = e.(Num).getN()
or
result =
e.(StrConst).getPrefix() + e.(StrConst).getText() +
e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "")
or
result = repr(e.(Subscript).getObject()) + "[" + repr(e.(Subscript).getIndex()) + "]"
or
(
if exists(e.(Call).getAnArg()) or exists(e.(Call).getANamedArg())
then result = repr(e.(Call).getFunc()) + "(..)"
else result = repr(e.(Call).getFunc()) + "()"
)
or
result = repr(e.(Attribute).getObject()) + "." + e.(Attribute).getName()
}
query predicate test_taint(string arg_location, string test_res, string function_name, string repr) {
exists(Call call, Expr arg, boolean expected_taint, boolean has_taint |
call.getLocation().getFile().getShortName() = "test.py" and
(
call.getFunc().(Name).getId() = "ensure_tainted" and
expected_taint = true
or
call.getFunc().(Name).getId() = "ensure_not_tainted" and
expected_taint = false
) and
arg = call.getAnArg() and
(
// 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()))
)
then has_taint = true
else has_taint = false
) and
(if expected_taint = has_taint then test_res = "ok " else test_res = "fail") and
// select
arg_location = arg.getLocation().toString() and
test_res = test_res and
function_name = call.getScope().(Function).getName() and
repr = repr(arg)
)
}

View File

@@ -0,0 +1,2 @@
| test.py:3:11:3:16 | ControlFlowNode for SOURCE | test.py:4:6:4:12 | ControlFlowNode for tainted |
| test.py:7:20:7:25 | ControlFlowNode for SOURCE | test.py:8:10:8:21 | ControlFlowNode for also_tainted |

View File

@@ -0,0 +1,22 @@
import python
import experimental.dataflow.TaintTracking
import experimental.dataflow.DataFlow
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
source.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
}
override predicate isSink(DataFlow::Node sink) {
exists(CallNode call |
call.getFunction().(NameNode).getId() = "SINK" and
sink.(DataFlow::CfgNode).getNode() = call.getAnArg()
)
}
}
from TestTaintTrackingConfiguration config, DataFlow::Node source, DataFlow::Node sink
where config.hasFlow(source, sink)
select source, sink

View File

@@ -0,0 +1,5 @@
| test.py:0:0:0:0 | SSA variable $ | test.py:0:0:0:0 | Exit node for Module test |
| test.py:7:5:7:16 | SSA variable also_tainted | test.py:8:5:8:22 | SSA variable also_tainted |
| test.py:7:5:7:16 | SSA variable also_tainted | test.py:8:10:8:21 | ControlFlowNode for also_tainted |
| test.py:7:20:7:25 | ControlFlowNode for SOURCE | test.py:7:5:7:16 | SSA variable also_tainted |
| test.py:8:5:8:22 | SSA variable also_tainted | test.py:6:1:6:11 | Exit node for Function func |

View File

@@ -0,0 +1,7 @@
import python
import experimental.dataflow.TaintTracking
import experimental.dataflow.DataFlow
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
where TaintTracking::localTaintStep(nodeFrom, nodeTo)
select nodeFrom, nodeTo

View File

@@ -0,0 +1,8 @@
# Module level taint is different from inside functions, since shared dataflow library
# relies on `getEnclosingCallable`
tainted = SOURCE
SINK(tainted)
def func():
also_tainted = SOURCE
SINK(also_tainted)

View File

@@ -0,0 +1,10 @@
| test.py:26 | ok | str_methods | ts.casefold() |
| test.py:28 | ok | str_methods | ts.format_map(..) |
| test.py:29 | fail | str_methods | "{unsafe}".format_map(..) |
| test.py:40 | fail | binary_decode_encode | base64.a85encode(..) |
| test.py:41 | fail | binary_decode_encode | base64.a85decode(..) |
| test.py:44 | fail | binary_decode_encode | base64.b85encode(..) |
| test.py:45 | fail | binary_decode_encode | base64.b85decode(..) |
| test.py:48 | fail | binary_decode_encode | base64.encodebytes(..) |
| test.py:49 | fail | binary_decode_encode | base64.decodebytes(..) |
| test.py:57 | ok | f_strings | Fstring |

View File

@@ -0,0 +1 @@
import experimental.dataflow.tainttracking.TestTaintLib

View File

@@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=1 --lang=3

View File

@@ -0,0 +1,64 @@
# Python 3 specific taint tracking for string
TAINTED_STRING = "TAINTED_STRING"
TAINTED_BYTES = b"TAINTED_BYTES"
def ensure_tainted(*args):
print("- ensure_tainted")
for i, arg in enumerate(args):
print("arg {}: {!r}".format(i, arg))
def ensure_not_tainted(*args):
print("- ensure_not_tainted")
for i, arg in enumerate(args):
print("arg {}: {!r}".format(i, arg))
# Actual tests
def str_methods():
print("\n# str_methods")
ts = TAINTED_STRING
tb = TAINTED_BYTES
ensure_tainted(
ts.casefold(),
ts.format_map({}),
"{unsafe}".format_map({"unsafe": ts}),
)
def binary_decode_encode():
print("\n#percent_fmt")
tb = TAINTED_BYTES
import base64
ensure_tainted(
# New in Python 3.4
base64.a85encode(tb),
base64.a85decode(base64.a85encode(tb)),
# New in Python 3.4
base64.b85encode(tb),
base64.b85decode(base64.b85encode(tb)),
# New in Python 3.1
base64.encodebytes(tb),
base64.decodebytes(base64.encodebytes(tb)),
)
def f_strings():
print("\n#f_strings")
ts = TAINTED_STRING
ensure_tainted(f"foo {ts} bar")
# Make tests runable
str_methods()
binary_decode_encode()
f_strings()

View File

@@ -0,0 +1,62 @@
| test.py:32 | ok | str_operations | ts |
| test.py:33 | ok | str_operations | BinaryExpr |
| test.py:34 | ok | str_operations | BinaryExpr |
| test.py:35 | ok | str_operations | BinaryExpr |
| test.py:36 | ok | str_operations | ts[Slice] |
| test.py:37 | ok | str_operations | ts[Slice] |
| test.py:38 | ok | str_operations | ts[Slice] |
| test.py:39 | ok | str_operations | ts[0] |
| test.py:40 | ok | str_operations | str(..) |
| test.py:41 | ok | str_operations | bytes(..) |
| test.py:42 | ok | str_operations | unicode(..) |
| test.py:51 | ok | str_methods | ts.capitalize() |
| test.py:52 | ok | str_methods | ts.center(..) |
| test.py:53 | ok | str_methods | ts.expandtabs() |
| test.py:55 | ok | str_methods | ts.format() |
| test.py:56 | ok | str_methods | "{}".format(..) |
| test.py:57 | ok | str_methods | "{unsafe}".format(..) |
| test.py:59 | ok | str_methods | ts.join(..) |
| test.py:60 | fail | str_methods | "".join(..) |
| test.py:62 | ok | str_methods | ts.ljust(..) |
| test.py:63 | ok | str_methods | ts.lstrip() |
| test.py:64 | ok | str_methods | ts.lower() |
| test.py:66 | ok | str_methods | ts.replace(..) |
| test.py:67 | ok | str_methods | "safe".replace(..) |
| test.py:69 | ok | str_methods | ts.rjust(..) |
| test.py:70 | ok | str_methods | ts.rstrip() |
| test.py:71 | ok | str_methods | ts.strip() |
| test.py:72 | ok | str_methods | ts.swapcase() |
| test.py:73 | ok | str_methods | ts.title() |
| test.py:74 | ok | str_methods | ts.upper() |
| test.py:75 | ok | str_methods | ts.zfill(..) |
| test.py:77 | ok | str_methods | ts.encode(..) |
| test.py:78 | ok | str_methods | ts.encode(..).decode(..) |
| test.py:80 | ok | str_methods | tb.decode(..) |
| test.py:81 | ok | str_methods | tb.decode(..).encode(..) |
| test.py:84 | ok | str_methods | ts.partition(..) |
| test.py:85 | ok | str_methods | ts.rpartition(..) |
| test.py:86 | ok | str_methods | ts.rsplit(..) |
| test.py:87 | ok | str_methods | ts.split(..) |
| test.py:88 | ok | str_methods | ts.splitlines() |
| test.py:93 | ok | str_methods | "safe".replace(..) |
| test.py:95 | fail | str_methods | ts.join(..) |
| test.py:96 | fail | str_methods | ts.join(..) |
| test.py:106 | fail | non_syntactic | meth() |
| test.py:107 | fail | non_syntactic | _str(..) |
| test.py:116 | ok | percent_fmt | BinaryExpr |
| test.py:117 | ok | percent_fmt | BinaryExpr |
| test.py:118 | fail | percent_fmt | BinaryExpr |
| test.py:128 | fail | binary_decode_encode | base64.b64encode(..) |
| test.py:129 | fail | binary_decode_encode | base64.b64decode(..) |
| test.py:131 | fail | binary_decode_encode | base64.standard_b64encode(..) |
| test.py:132 | fail | binary_decode_encode | base64.standard_b64decode(..) |
| test.py:134 | fail | binary_decode_encode | base64.urlsafe_b64encode(..) |
| test.py:135 | fail | binary_decode_encode | base64.urlsafe_b64decode(..) |
| test.py:137 | fail | binary_decode_encode | base64.b32encode(..) |
| test.py:138 | fail | binary_decode_encode | base64.b32decode(..) |
| test.py:140 | fail | binary_decode_encode | base64.b16encode(..) |
| test.py:141 | fail | binary_decode_encode | base64.b16decode(..) |
| test.py:156 | fail | binary_decode_encode | base64.encodestring(..) |
| test.py:157 | fail | binary_decode_encode | base64.decodestring(..) |
| test.py:162 | fail | binary_decode_encode | quopri.encodestring(..) |
| test.py:163 | fail | binary_decode_encode | quopri.decodestring(..) |

View File

@@ -0,0 +1 @@
import experimental.dataflow.tainttracking.TestTaintLib

View File

@@ -0,0 +1,173 @@
import sys
if sys.version_info[0] == 3:
unicode = str
TAINTED_STRING = "TAINTED_STRING"
TAINTED_BYTES = b"TAINTED_BYTES"
def ensure_tainted(*args):
print("- ensure_tainted")
for i, arg in enumerate(args):
print("arg {}: {!r}".format(i, arg))
def ensure_not_tainted(*args):
print("- ensure_not_tainted")
for i, arg in enumerate(args):
print("arg {}: {!r}".format(i, arg))
# Actual tests
def str_operations():
print("\n# str_operations")
ts = TAINTED_STRING
tb = TAINTED_BYTES
ensure_tainted(
ts,
ts + "foo",
"foo" + ts,
ts * 5,
ts[0 : len(ts)],
ts[:],
ts[0:1000],
ts[0],
str(ts),
bytes(tb),
unicode(ts),
)
def str_methods():
print("\n# str_methods")
ts = TAINTED_STRING
tb = TAINTED_BYTES
ensure_tainted(
ts.capitalize(),
ts.center(100),
ts.expandtabs(),
ts.format(),
"{}".format(ts),
"{unsafe}".format(unsafe=ts),
ts.join(["", ""]),
"".join([ts]),
ts.ljust(100),
ts.lstrip(),
ts.lower(),
ts.replace("old", "new"),
"safe".replace("safe", ts),
ts.rjust(100),
ts.rstrip(),
ts.strip(),
ts.swapcase(),
ts.title(),
ts.upper(),
ts.zfill(100),
ts.encode("utf-8"),
ts.encode("utf-8").decode("utf-8"),
tb.decode("utf-8"),
tb.decode("utf-8").encode("utf-8"),
# string methods that return a list
ts.partition("_"),
ts.rpartition("_"),
ts.rsplit("_"),
ts.split("_"),
ts.splitlines(),
)
ensure_not_tainted(
# Intuitively I think this should be safe, but better discuss it
"safe".replace(ts, "also-safe"),
ts.join([]), # FP due to separator not being used with zero/one elements
ts.join(["safe"]), # FP due to separator not being used with zero/one elements
)
def non_syntactic():
print("\n# non_syntactic")
ts = TAINTED_STRING
meth = ts.upper
_str = str
ensure_tainted(
meth(),
_str(ts),
)
def percent_fmt():
print("\n#percent_fmt")
ts = TAINTED_STRING
tainted_fmt = ts + " %s %s"
ensure_tainted(
tainted_fmt % (1, 2),
"%s foo bar" % ts,
"%s %s %s" % (1, 2, ts),
)
def binary_decode_encode():
print("\n#percent_fmt")
tb = TAINTED_BYTES
import base64
ensure_tainted(
base64.b64encode(tb),
base64.b64decode(base64.b64encode(tb)),
base64.standard_b64encode(tb),
base64.standard_b64decode(base64.standard_b64encode(tb)),
base64.urlsafe_b64encode(tb),
base64.urlsafe_b64decode(base64.urlsafe_b64encode(tb)),
base64.b32encode(tb),
base64.b32decode(base64.b32encode(tb)),
base64.b16encode(tb),
base64.b16decode(base64.b16encode(tb)),
# # New in Python 3.4
# base64.a85encode(tb),
# base64.a85decode(base64.a85encode(tb)),
# # New in Python 3.4
# base64.b85encode(tb),
# base64.b85decode(base64.b85encode(tb)),
# # New in Python 3.1
# base64.encodebytes(tb),
# base64.decodebytes(base64.encodebytes(tb)),
# deprecated since Python 3.1, but still works
base64.encodestring(tb),
base64.decodestring(base64.encodestring(tb)),
)
import quopri
ensure_tainted(
quopri.encodestring(tb),
quopri.decodestring(quopri.encodestring(tb)),
)
# Make tests runable
str_operations()
str_methods()
non_syntactic()
percent_fmt()
binary_decode_encode()