mirror of
https://github.com/github/codeql.git
synced 2026-05-04 21:25:44 +02:00
python: fix implementation of lambdaCreation
- still identifying summarized callables by name. I think ther shoudl perhaps be a `getAUse` next to `getACall`. - also fix tests, adding a standard taint configuration
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import python
|
||||
import experimental.dataflow.TestUtil.FlowTest
|
||||
import experimental.dataflow.testTaintConfig
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
|
||||
class DataFlowTest extends FlowTest {
|
||||
DataFlowTest() { this = "DataFlowTest" }
|
||||
|
||||
override string flowTag() { result = "flow" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
|
||||
query predicate missingAnnotationOnSINK(Location location, string error, string element) {
|
||||
error = "ERROR, you should add `# $ MISSING: flow` annotation" and
|
||||
exists(DataFlow::Node sink |
|
||||
exists(DataFlow::CallCfgNode call |
|
||||
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
|
||||
call.getFunction().asCfgNode().(NameNode).getId() = "SINK" and
|
||||
(sink = call.getArg(_) or sink = call.getArgByName(_))
|
||||
) and
|
||||
location = sink.getLocation() and
|
||||
element = prettyExpr(sink.asExpr()) and
|
||||
not any(TestConfiguration config).hasFlow(_, sink) and
|
||||
not exists(FalseNegativeExpectation missingResult |
|
||||
missingResult.getTag() = "flow" and
|
||||
missingResult.getLocation().getFile() = location.getFile() and
|
||||
missingResult.getLocation().getStartLine() = location.getStartLine()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
import python
|
||||
private import TestSummaries
|
||||
import experimental.dataflow.TestUtil.NormalDataflowTest
|
||||
import experimental.dataflow.TestUtil.NormalTaintTrackingTest
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
edges
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:32:20:32:25 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:36:48:36:53 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:44:25:44:32 | ControlFlowNode for List |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:44:26:44:31 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:51:34:51:39 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:57:51:57:56 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:60:41:60:46 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:64:33:64:38 | ControlFlowNode for SOURCE |
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:65:6:65:26 | ControlFlowNode for Subscript |
|
||||
| summaries.py:32:11:32:26 | ControlFlowNode for identity() | summaries.py:33:6:33:12 | ControlFlowNode for tainted |
|
||||
| summaries.py:32:20:32:25 | ControlFlowNode for SOURCE | summaries.py:32:11:32:26 | ControlFlowNode for identity() |
|
||||
| summaries.py:36:18:36:54 | ControlFlowNode for apply_lambda() | summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda |
|
||||
@@ -15,6 +6,7 @@ edges
|
||||
| summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] |
|
||||
| summaries.py:44:25:44:32 | ControlFlowNode for List | summaries.py:45:6:45:20 | ControlFlowNode for Subscript |
|
||||
| summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] |
|
||||
| summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:44:25:44:32 | ControlFlowNode for List |
|
||||
| summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:44:25:44:32 | ControlFlowNode for List [List element] |
|
||||
| summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | summaries.py:45:6:45:20 | ControlFlowNode for Subscript |
|
||||
| summaries.py:51:18:51:41 | ControlFlowNode for map() [List element] | summaries.py:52:6:52:19 | ControlFlowNode for tainted_mapped [List element] |
|
||||
@@ -31,9 +23,9 @@ edges
|
||||
| summaries.py:61:6:61:27 | ControlFlowNode for tainted_mapped_summary [List element] | summaries.py:61:6:61:30 | ControlFlowNode for Subscript |
|
||||
| summaries.py:64:22:64:39 | ControlFlowNode for json_loads() [List element] | summaries.py:65:6:65:23 | ControlFlowNode for tainted_resultlist [List element] |
|
||||
| summaries.py:64:33:64:38 | ControlFlowNode for SOURCE | summaries.py:64:22:64:39 | ControlFlowNode for json_loads() [List element] |
|
||||
| summaries.py:64:33:64:38 | ControlFlowNode for SOURCE | summaries.py:65:6:65:26 | ControlFlowNode for Subscript |
|
||||
| summaries.py:65:6:65:23 | ControlFlowNode for tainted_resultlist [List element] | summaries.py:65:6:65:26 | ControlFlowNode for Subscript |
|
||||
nodes
|
||||
| summaries.py:10:10:10:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
|
||||
| summaries.py:32:11:32:26 | ControlFlowNode for identity() | semmle.label | ControlFlowNode for identity() |
|
||||
| summaries.py:32:20:32:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| summaries.py:33:6:33:12 | ControlFlowNode for tainted | semmle.label | ControlFlowNode for tainted |
|
||||
@@ -68,10 +60,10 @@ nodes
|
||||
subpaths
|
||||
invalidSpecComponent
|
||||
#select
|
||||
| summaries.py:33:6:33:12 | ControlFlowNode for tainted | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:33:6:33:12 | ControlFlowNode for tainted | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:45:6:45:20 | ControlFlowNode for Subscript | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:52:6:52:22 | ControlFlowNode for Subscript | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:52:6:52:22 | ControlFlowNode for Subscript | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:58:6:58:31 | ControlFlowNode for Subscript | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:58:6:58:31 | ControlFlowNode for Subscript | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:61:6:61:30 | ControlFlowNode for Subscript | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:61:6:61:30 | ControlFlowNode for Subscript | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:65:6:65:26 | ControlFlowNode for Subscript | summaries.py:10:10:10:17 | ControlFlowNode for Str | summaries.py:65:6:65:26 | ControlFlowNode for Subscript | $@ | summaries.py:10:10:10:17 | ControlFlowNode for Str | ControlFlowNode for Str |
|
||||
| summaries.py:33:6:33:12 | ControlFlowNode for tainted | summaries.py:32:20:32:25 | ControlFlowNode for SOURCE | summaries.py:33:6:33:12 | ControlFlowNode for tainted | $@ | summaries.py:32:20:32:25 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
| summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | $@ | summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
| summaries.py:45:6:45:20 | ControlFlowNode for Subscript | summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | $@ | summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
| summaries.py:52:6:52:22 | ControlFlowNode for Subscript | summaries.py:51:34:51:39 | ControlFlowNode for SOURCE | summaries.py:52:6:52:22 | ControlFlowNode for Subscript | $@ | summaries.py:51:34:51:39 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
| summaries.py:58:6:58:31 | ControlFlowNode for Subscript | summaries.py:57:51:57:56 | ControlFlowNode for SOURCE | summaries.py:58:6:58:31 | ControlFlowNode for Subscript | $@ | summaries.py:57:51:57:56 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
| summaries.py:61:6:61:30 | ControlFlowNode for Subscript | summaries.py:60:41:60:46 | ControlFlowNode for SOURCE | summaries.py:61:6:61:30 | ControlFlowNode for Subscript | $@ | summaries.py:60:41:60:46 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
| summaries.py:65:6:65:26 | ControlFlowNode for Subscript | summaries.py:64:33:64:38 | ControlFlowNode for SOURCE | summaries.py:65:6:65:26 | ControlFlowNode for Subscript | $@ | summaries.py:64:33:64:38 | ControlFlowNode for SOURCE | ControlFlowNode for SOURCE |
|
||||
|
||||
@@ -38,7 +38,7 @@ SINK(tainted_lambda) # $ flow="SOURCE, l:-1 -> tainted_lambda"
|
||||
|
||||
# A lambda that breaks the flow
|
||||
untainted_lambda = apply_lambda(lambda x: 1, SOURCE)
|
||||
SINK_F(untainted_lambda) # $ SPURIOUS: flow="SOURCE, l:-1 -> untainted_lambda"
|
||||
SINK_F(untainted_lambda)
|
||||
|
||||
# Collection summaries
|
||||
tainted_list = reversed([SOURCE])
|
||||
|
||||
@@ -8,6 +8,7 @@ import DataFlow::PathGraph
|
||||
import semmle.python.dataflow.new.TaintTracking
|
||||
import semmle.python.dataflow.new.internal.FlowSummaryImpl
|
||||
import semmle.python.ApiGraphs
|
||||
import experimental.dataflow.testTaintConfig
|
||||
private import TestSummaries
|
||||
|
||||
query predicate invalidSpecComponent(SummarizedCallable sc, string s, string c) {
|
||||
@@ -15,19 +16,6 @@ query predicate invalidSpecComponent(SummarizedCallable sc, string s, string c)
|
||||
Private::External::invalidSpecComponent(s, c)
|
||||
}
|
||||
|
||||
class Conf extends TaintTracking::Configuration {
|
||||
Conf() { this = "FlowSummaries" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr().(StrConst).getS() = "source" }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(Call mc |
|
||||
mc.getFunc().(Name).getId() = "SINK" and
|
||||
mc.getAnArg() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, TestConfiguration conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink, source, sink, "$@", source, source.toString()
|
||||
|
||||
51
python/ql/test/experimental/dataflow/testTaintConfig.qll
Normal file
51
python/ql/test/experimental/dataflow/testTaintConfig.qll
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Configuration to test selected data flow
|
||||
* Sources in the source code are denoted by the special name `SOURCE`,
|
||||
* and sinks are denoted by arguments to the special function `SINK`.
|
||||
* For example, given the test code
|
||||
* ```python
|
||||
* def test():
|
||||
* s = SOURCE
|
||||
* SINK(s)
|
||||
* ```
|
||||
* `SOURCE` will be a source and the second occurance of `s` will be a sink.
|
||||
*
|
||||
* In order to test literals, alternative sources are defined for each type:
|
||||
*
|
||||
* for | use
|
||||
* ----------
|
||||
* string | `"source"`
|
||||
* integer | `42`
|
||||
* float | `42.0`
|
||||
* complex | `42j` (not supported yet)
|
||||
*/
|
||||
|
||||
private import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.dataflow.new.TaintTracking
|
||||
|
||||
class TestConfiguration extends TaintTracking::Configuration {
|
||||
TestConfiguration() { this = "TestConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) {
|
||||
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
|
||||
or
|
||||
node.(DataFlow::CfgNode).getNode().getNode().(StrConst).getS() = "source"
|
||||
or
|
||||
node.(DataFlow::CfgNode).getNode().getNode().(IntegerLiteral).getN() = "42"
|
||||
or
|
||||
node.(DataFlow::CfgNode).getNode().getNode().(FloatLiteral).getN() = "42.0"
|
||||
// No support for complex numbers
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() in ["SINK", "SINK_F"] and
|
||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizerIn(DataFlow::Node node) { this.isSource(node) }
|
||||
|
||||
override int explorationLimit() { result = 5 }
|
||||
}
|
||||
Reference in New Issue
Block a user