mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Python: Add test for "hidden" import * flow
TL;DR: We were missing out on flow in the following situation: `mod1.py`: ```python foo = SOURCE ``` `mod2.py`: ```python from mod1 import * ``` `test.py`: ```python from mod2 import foo SINK(foo) ``` This is because there's no node at which a read of `foo` takes place within `test.py`, and so the added reads make no difference. Unfortunately, this means the previous test was a bit too simplistic, since it only looks for module variable reads and writes. Because of this, we change the test to be a more traditional "all flow" style (though restricted to `CfgNode`s).
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
moduleVariables
|
||||
| three.py:0:0:0:0 | ModuleVariableNode for three.foo |
|
||||
| trois.py:0:0:0:0 | ModuleVariableNode for trois.foo |
|
||||
reads
|
||||
| three.py:0:0:0:0 | ModuleVariableNode for three.foo | test1.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| three.py:0:0:0:0 | ModuleVariableNode for three.foo | two.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| trois.py:0:0:0:0 | ModuleVariableNode for trois.foo | deux.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| trois.py:0:0:0:0 | ModuleVariableNode for trois.foo | test2.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
writes
|
||||
| three.py:1:1:1:3 | GSSA Variable foo | three.py:0:0:0:0 | ModuleVariableNode for three.foo |
|
||||
| trois.py:1:1:1:3 | GSSA Variable foo | trois.py:0:0:0:0 | ModuleVariableNode for trois.foo |
|
||||
| test3.py:1:17:1:19 | ControlFlowNode for ImportMember | test3.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| three.py:1:1:1:3 | ControlFlowNode for foo | test1.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| three.py:1:1:1:3 | ControlFlowNode for foo | two.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| three.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test1.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| three.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | two.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| trois.py:1:1:1:3 | ControlFlowNode for foo | deux.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| trois.py:1:1:1:3 | ControlFlowNode for foo | test2.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | deux.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
| trois.py:1:7:1:7 | ControlFlowNode for IntegerLiteral | test2.py:2:7:2:9 | ControlFlowNode for foo |
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
|
||||
query DataFlow::Node moduleVariables() { result instanceof DataFlow::ModuleVariableNode }
|
||||
/**
|
||||
* A configuration to find all flows.
|
||||
* To be used on tiny programs.
|
||||
*/
|
||||
class AllFlowsConfig extends DataFlow::Configuration {
|
||||
AllFlowsConfig() { this = "AllFlowsConfig" }
|
||||
|
||||
query predicate reads(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
fromNode.(DataFlow::ModuleVariableNode).getARead() = toNode
|
||||
override predicate isSource(DataFlow::Node node) { any() }
|
||||
|
||||
override predicate isSink(DataFlow::Node node) { any() }
|
||||
}
|
||||
|
||||
query predicate writes(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
fromNode = toNode.(DataFlow::ModuleVariableNode).getAWrite()
|
||||
}
|
||||
from DataFlow::CfgNode source, DataFlow::CfgNode sink
|
||||
where
|
||||
source != sink and
|
||||
exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink))
|
||||
select source, sink
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
from one import foo
|
||||
print(foo)
|
||||
Reference in New Issue
Block a user