mirror of
https://github.com/github/codeql.git
synced 2026-05-05 21:55:19 +02:00
python: Flow summaries based on type tracking
Two classes have been inserted into the hierarchies: - `NonLibraryDataFlowCallable` with a method `getACall2`. This method implements "get a call, not considering flow summaries". For `NonLibraryDataFlowCallable`s, `getACall` will defer to `getACall2`. While you could have a synthesised call to such a callable, it would not correspond to a `CallNode`. - `NonLibraryDataFlowSourceCall` with methods `getArg2` and `getCallable2`. These also refer to a call graph that does not consider flow summaries. `getArg2` is used to synthesise pre-update nodes for arguments. `getCallable2` is used in `connects` to compute argument passing. This is used to define data flow nodes for overflow arguments. `getACall2` ensures that `LibraryCallableValue::getACall` is not called when the charpred of `FunctionCall` is evaluated.
This commit is contained in:
@@ -2,6 +2,7 @@ import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||
|
||||
/**
|
||||
* A routing test is designed to test that values are routed to the
|
||||
@@ -48,6 +49,6 @@ abstract class RoutingTest extends InlineExpectationsTest {
|
||||
|
||||
pragma[inline]
|
||||
private string toFunc(DataFlow::Node toNode) {
|
||||
result = toNode.getEnclosingCallable().getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing?
|
||||
result = toNode.getEnclosingCallable().(DataFlowPrivate::NonLibraryDataFlowCallable).getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ private class SummarizedCallableMap extends SummarizedCallable {
|
||||
}
|
||||
// Typetracking needs to use a local flow step not including summaries
|
||||
// Typetracking needs to use a call graph not including summaries
|
||||
// private class SummarizedCallableJsonLoads extends SummarizedCallable {
|
||||
// SummarizedCallableJsonLoads() { this = "json.loads" }
|
||||
// override Call getACall() {
|
||||
// result = API::moduleImport("json").getMember("loads").getACall().asExpr()
|
||||
// }
|
||||
// override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
// input = "Argument[0]" and
|
||||
// output = "ReturnValue.ListElement" and
|
||||
// preservesValue = true
|
||||
// }
|
||||
// }
|
||||
private class SummarizedCallableJsonLoads extends SummarizedCallable {
|
||||
SummarizedCallableJsonLoads() { this = "json.loads" }
|
||||
override Call getACall() {
|
||||
result = API::moduleImport("json").getMember("loads").getACall().asExpr()
|
||||
}
|
||||
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and
|
||||
output = "ReturnValue.ListElement" and
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ edges
|
||||
| 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() |
|
||||
@@ -28,6 +29,9 @@ edges
|
||||
| summaries.py:60:40:60:47 | ControlFlowNode for List [List element] | summaries.py:60:26:60:48 | ControlFlowNode for map() [List element] |
|
||||
| summaries.py:60:41:60:46 | ControlFlowNode for SOURCE | summaries.py:60:40:60:47 | ControlFlowNode for List [List element] |
|
||||
| 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: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() |
|
||||
@@ -57,6 +61,9 @@ nodes
|
||||
| summaries.py:60:41:60:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| summaries.py:61:6:61:27 | ControlFlowNode for tainted_mapped_summary [List element] | semmle.label | ControlFlowNode for tainted_mapped_summary [List element] |
|
||||
| summaries.py:61:6:61:30 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| summaries.py:64:22:64:39 | ControlFlowNode for json_loads() [List element] | semmle.label | ControlFlowNode for json_loads() [List element] |
|
||||
| summaries.py:64:33:64:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
|
||||
| summaries.py:65:6:65:23 | ControlFlowNode for tainted_resultlist [List element] | semmle.label | ControlFlowNode for tainted_resultlist [List element] |
|
||||
| summaries.py:65:6:65:26 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
subpaths
|
||||
invalidSpecComponent
|
||||
|
||||
@@ -62,4 +62,4 @@ SINK(tainted_mapped_summary[0]) # $ flow="SOURCE, l:-1 -> tainted_mapped_summar
|
||||
|
||||
from json import loads as json_loads
|
||||
tainted_resultlist = json_loads(SOURCE)
|
||||
SINK(tainted_resultlist[0]) # $ MISSING: flow
|
||||
SINK(tainted_resultlist[0]) # $ flow="SOURCE, l:-1 -> tainted_resultlist[0]"
|
||||
|
||||
Reference in New Issue
Block a user