@@ -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 ( ) {
0 commit comments