Python: Model invoke.context.Context

This commit is contained in:
Rasmus Wriedt Larsen
2020-10-07 12:16:53 +02:00
parent 4ef5202382
commit ebff1794fc
2 changed files with 63 additions and 8 deletions

View File

@@ -34,7 +34,7 @@ private module Invoke {
* WARNING: Only holds for a few predefined attributes. * WARNING: Only holds for a few predefined attributes.
*/ */
private DataFlow::Node invoke_attr(DataFlow::TypeTracker t, string attr_name) { private DataFlow::Node invoke_attr(DataFlow::TypeTracker t, string attr_name) {
attr_name in ["run", "sudo"] and attr_name in ["run", "sudo", "context", "Context"] and
( (
t.start() and t.start() and
result = DataFlow::importMember("invoke", attr_name) result = DataFlow::importMember("invoke", attr_name)
@@ -69,15 +69,73 @@ private module Invoke {
} }
/** Provides models for the `invoke` module. */ /** Provides models for the `invoke` module. */
module invoke { } module invoke {
/** Gets a reference to the `invoke.context` module. */
DataFlow::Node context() { result = invoke_attr("context") }
/** Provides models for the `invoke.context` module */
module context {
/** Provides models for the `invoke.context.Context` class */
module Context {
/** Gets a reference to the `invoke.context.Context` class. */
private DataFlow::Node class_(DataFlow::TypeTracker t) {
t.start() and
result = DataFlow::importMember("invoke.context", "Context")
or
t.startInAttr("Context") and
result = invoke::context()
or
t.start() and
result = invoke_attr("Context")
or
exists(DataFlow::TypeTracker t2 | result = class_(t2).track(t2, t))
}
/** Gets a reference to the `invoke.context.Context` class. */
DataFlow::Node class_() { result = class_(DataFlow::TypeTracker::end()) }
/** Gets a reference to an instance of `invoke.context.Context`. */
private DataFlow::Node instance(DataFlow::TypeTracker t) {
t.start() and
result.asCfgNode().(CallNode).getFunction() =
invoke::context::Context::class_().asCfgNode()
or
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
}
/** Gets a reference to an instance of `invoke.context.Context`. */
DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) }
/** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
private DataFlow::Node instanceRunMethods(DataFlow::TypeTracker t) {
t.startInAttr(["run", "sudo"]) and
result = invoke::context::Context::instance()
or
exists(DataFlow::TypeTracker t2 | result = instanceRunMethods(t2).track(t2, t))
}
/** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
DataFlow::Node instanceRunMethods() {
result = instanceRunMethods(DataFlow::TypeTracker::end())
}
}
}
}
/** /**
* A call to either of the `invoke.run` or `invoke.sudo` functions * A call to either
* See http://docs.pyinvoke.org/en/stable/api/__init__.html * - `invoke.run` or `invoke.sudo` functions (http://docs.pyinvoke.org/en/stable/api/__init__.html)
* - `run` or `sudo` methods on a `invoke.context.Context` instance (http://docs.pyinvoke.org/en/stable/api/context.html#invoke.context.Context.run)
*/ */
private class InvokeRunCommandCall extends SystemCommandExecution::Range { private class InvokeRunCommandCall extends SystemCommandExecution::Range {
InvokeRunCommandCall() { InvokeRunCommandCall() {
this.asCfgNode().(CallNode).getFunction() = invoke_attr(["run", "sudo"]).asCfgNode() exists(DataFlow::Node callFunction |
this.asCfgNode().(CallNode).getFunction() = callFunction.asCfgNode()
|
callFunction = invoke_attr(["run", "sudo"])
or
callFunction = invoke::context::Context::instanceRunMethods()
)
} }
override DataFlow::Node getCommand() { override DataFlow::Node getCommand() {

View File

@@ -1,5 +1,2 @@
| invoke_test.py:19:26:19:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
| invoke_test.py:20:27:20:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
| invoke_test.py:24:27:24:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
| invoke_test.py:31:26:31:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:31:26:31:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
| invoke_test.py:38:26:38:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:38:26:38:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |