Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ce57a28

Browse files
committed
Python: Use CallableValue and improve tests
1 parent f24dc69 commit ce57a28

4 files changed

Lines changed: 27 additions & 9 deletions

File tree

python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,24 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
7171
//--------
7272

7373
/** Represents a callable */
74-
class DataFlowCallable = FunctionObject; // TODO: consider CallableValue
74+
class DataFlowCallable = CallableValue;
7575

7676
/** Represents a call to a callable */
7777
class DataFlowCall extends CallNode {
78+
DataFlowCallable callable;
79+
80+
DataFlowCall() {
81+
this = callable.getACall()
82+
}
83+
7884
/** Gets the enclosing callable of this call. */
79-
abstract DataFlowCallable getEnclosingCallable();
85+
DataFlowCallable getEnclosingCallable() { result = callable }
8086
}
8187

8288
/** A data flow node that represents a call argument. */
8389
class ArgumentNode extends Node {
8490
ArgumentNode() {
85-
exists( DataFlowCall call, int pos |
91+
exists(DataFlowCall call, int pos |
8692
this.asCfgNode() = call.getArg(pos)
8793
)
8894
}
@@ -96,14 +102,9 @@ class ArgumentNode extends Node {
96102
final DataFlowCall getCall() { this.argumentOf(result, _) }
97103
}
98104

99-
import semmle.python.pointsto.CallGraph
100-
101105
/** Gets a viable run-time target for the call `call`. */
102106
DataFlowCallable viableCallable(DataFlowCall call) {
103-
exists(FunctionInvocation i |
104-
call = i.getCall() and
105-
result = i.getFunction()
106-
)
107+
result = call.getEnclosingCallable()
107108
}
108109

109110
private newtype TReturnKind = TNormalReturnKind()

python/ql/test/experimental/dataflow/allFlowsConfig.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ class AllFlowsConfig extends DataFlow::Configuration {
99

1010
override predicate isSource(DataFlow::Node node) {
1111
node.asCfgNode().isEntryNode()
12+
or
13+
node = DataFlow::TEssaNode(_) and
14+
not exists(DataFlow::Node pred |
15+
pred = DataFlow::TEssaNode(_) and
16+
DataFlow::localFlowStep(pred, node)
17+
)
1218
}
1319

1420
override predicate isSink(DataFlow::Node node) {

python/ql/test/experimental/dataflow/local.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
| test.py:1:5:1:5 | ControlFlowNode for IntegerLiteral | test.py:1:1:1:1 | GSSA Variable a |
33
| test.py:2:5:2:5 | ControlFlowNode for a | test.py:2:1:2:1 | GSSA Variable b |
44
| test.py:4:1:4:9 | ControlFlowNode for FunctionExpr | test.py:4:5:4:5 | GSSA Variable f |
5+
| test.py:4:7:4:7 | ControlFlowNode for x | test.py:4:7:4:7 | SSA variable x |
56
| test.py:5:7:5:11 | ControlFlowNode for BinaryExpr | test.py:5:3:5:3 | SSA variable y |
67
| test.py:8:5:8:8 | ControlFlowNode for f() | test.py:8:1:8:1 | GSSA Variable c |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
| test.py:0:0:0:0 | Entry node for Module test |
2+
| test.py:0:0:0:0 | GSSA Variable __name__ |
3+
| test.py:0:0:0:0 | GSSA Variable __package__ |
4+
| test.py:0:0:0:0 | GSSA Variable c |
5+
| test.py:0:0:0:0 | SSA variable $ |
6+
| test.py:1:1:1:1 | GSSA Variable a |
7+
| test.py:2:1:2:1 | GSSA Variable b |
28
| test.py:4:1:4:9 | Entry node for Function f |
9+
| test.py:4:5:4:5 | GSSA Variable f |
10+
| test.py:4:7:4:7 | SSA variable x |
11+
| test.py:5:3:5:3 | SSA variable y |
12+
| test.py:8:1:8:1 | GSSA Variable c |

0 commit comments

Comments
 (0)