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

Skip to content

Commit ebff179

Browse files
committed
Python: Model invoke.context.Context
1 parent 4ef5202 commit ebff179

2 files changed

Lines changed: 63 additions & 8 deletions

File tree

python/ql/src/experimental/semmle/python/frameworks/Invoke.qll

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ private module Invoke {
3434
* WARNING: Only holds for a few predefined attributes.
3535
*/
3636
private DataFlow::Node invoke_attr(DataFlow::TypeTracker t, string attr_name) {
37-
attr_name in ["run", "sudo"] and
37+
attr_name in ["run", "sudo", "context", "Context"] and
3838
(
3939
t.start() and
4040
result = DataFlow::importMember("invoke", attr_name)
@@ -69,15 +69,73 @@ private module Invoke {
6969
}
7070

7171
/** Provides models for the `invoke` module. */
72-
module invoke { }
72+
module invoke {
73+
/** Gets a reference to the `invoke.context` module. */
74+
DataFlow::Node context() { result = invoke_attr("context") }
75+
76+
/** Provides models for the `invoke.context` module */
77+
module context {
78+
/** Provides models for the `invoke.context.Context` class */
79+
module Context {
80+
/** Gets a reference to the `invoke.context.Context` class. */
81+
private DataFlow::Node class_(DataFlow::TypeTracker t) {
82+
t.start() and
83+
result = DataFlow::importMember("invoke.context", "Context")
84+
or
85+
t.startInAttr("Context") and
86+
result = invoke::context()
87+
or
88+
t.start() and
89+
result = invoke_attr("Context")
90+
or
91+
exists(DataFlow::TypeTracker t2 | result = class_(t2).track(t2, t))
92+
}
93+
94+
/** Gets a reference to the `invoke.context.Context` class. */
95+
DataFlow::Node class_() { result = class_(DataFlow::TypeTracker::end()) }
96+
97+
/** Gets a reference to an instance of `invoke.context.Context`. */
98+
private DataFlow::Node instance(DataFlow::TypeTracker t) {
99+
t.start() and
100+
result.asCfgNode().(CallNode).getFunction() =
101+
invoke::context::Context::class_().asCfgNode()
102+
or
103+
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
104+
}
105+
106+
/** Gets a reference to an instance of `invoke.context.Context`. */
107+
DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) }
108+
109+
/** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
110+
private DataFlow::Node instanceRunMethods(DataFlow::TypeTracker t) {
111+
t.startInAttr(["run", "sudo"]) and
112+
result = invoke::context::Context::instance()
113+
or
114+
exists(DataFlow::TypeTracker t2 | result = instanceRunMethods(t2).track(t2, t))
115+
}
116+
117+
/** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
118+
DataFlow::Node instanceRunMethods() {
119+
result = instanceRunMethods(DataFlow::TypeTracker::end())
120+
}
121+
}
122+
}
123+
}
73124

74125
/**
75-
* A call to either of the `invoke.run` or `invoke.sudo` functions
76-
* See http://docs.pyinvoke.org/en/stable/api/__init__.html
126+
* A call to either
127+
* - `invoke.run` or `invoke.sudo` functions (http://docs.pyinvoke.org/en/stable/api/__init__.html)
128+
* - `run` or `sudo` methods on a `invoke.context.Context` instance (http://docs.pyinvoke.org/en/stable/api/context.html#invoke.context.Context.run)
77129
*/
78130
private class InvokeRunCommandCall extends SystemCommandExecution::Range {
79131
InvokeRunCommandCall() {
80-
this.asCfgNode().(CallNode).getFunction() = invoke_attr(["run", "sudo"]).asCfgNode()
132+
exists(DataFlow::Node callFunction |
133+
this.asCfgNode().(CallNode).getFunction() = callFunction.asCfgNode()
134+
|
135+
callFunction = invoke_attr(["run", "sudo"])
136+
or
137+
callFunction = invoke::context::Context::instanceRunMethods()
138+
)
81139
}
82140

83141
override DataFlow::Node getCommand() {
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
| invoke_test.py:19:26:19:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
2-
| invoke_test.py:20:27:20:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
3-
| invoke_test.py:24:27:24:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
41
| invoke_test.py:31:26:31:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
52
| invoke_test.py:38:26:38:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |

0 commit comments

Comments
 (0)