66private import python
77private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.Concepts
9+ private import semmle.python.ApiGraphs
910
1011/**
1112 * Provides models for the `invoke` PyPI package.
@@ -16,102 +17,44 @@ private module Invoke {
1617 // invoke
1718 // ---------------------------------------------------------------------------
1819 /** Gets a reference to the `invoke` module. */
19- private DataFlow:: Node invoke ( DataFlow:: TypeTracker t ) {
20- t .start ( ) and
21- result = DataFlow:: importNode ( "invoke" )
22- or
23- exists ( DataFlow:: TypeTracker t2 | result = invoke ( t2 ) .track ( t2 , t ) )
24- }
25-
26- /** Gets a reference to the `invoke` module. */
27- DataFlow:: Node invoke ( ) { result = invoke ( DataFlow:: TypeTracker:: end ( ) ) }
28-
29- /**
30- * Gets a reference to the attribute `attr_name` of the `invoke` module.
31- * WARNING: Only holds for a few predefined attributes.
32- */
33- private DataFlow:: Node invoke_attr ( DataFlow:: TypeTracker t , string attr_name ) {
34- attr_name in [ "run" , "sudo" , "context" , "Context" , "task" ] and
35- (
36- t .start ( ) and
37- result = DataFlow:: importNode ( "invoke." + attr_name )
38- or
39- t .startInAttr ( attr_name ) and
40- result = DataFlow:: importNode ( "invoke" )
41- )
42- or
43- // Due to bad performance when using normal setup with `invoke_attr(t2, attr_name).track(t2, t)`
44- // we have inlined that code and forced a join
45- exists ( DataFlow:: TypeTracker t2 |
46- exists ( DataFlow:: StepSummary summary |
47- invoke_attr_first_join ( t2 , attr_name , result , summary ) and
48- t = t2 .append ( summary )
49- )
50- )
51- }
52-
53- pragma [ nomagic]
54- private predicate invoke_attr_first_join (
55- DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res , DataFlow:: StepSummary summary
56- ) {
57- DataFlow:: StepSummary:: step ( invoke_attr ( t2 , attr_name ) , res , summary )
58- }
59-
60- /**
61- * Gets a reference to the attribute `attr_name` of the `invoke` module.
62- * WARNING: Only holds for a few predefined attributes.
63- */
64- private DataFlow:: Node invoke_attr ( string attr_name ) {
65- result = invoke_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
66- }
20+ API:: Node invoke ( ) { result = API:: moduleImport ( "invoke" ) }
6721
6822 /** Provides models for the `invoke` module. */
6923 module invoke {
7024 /** Gets a reference to the `invoke.context` module. */
71- DataFlow :: Node context ( ) { result = invoke_attr ( "context" ) }
25+ API :: Node context ( ) { result = invoke ( ) . getMember ( "context" ) }
7226
7327 /** Provides models for the `invoke.context` module */
7428 module context {
7529 /** Provides models for the `invoke.context.Context` class */
7630 module Context {
7731 /** Gets a reference to the `invoke.context.Context` class. */
78- private DataFlow:: Node classRef ( DataFlow:: TypeTracker t ) {
79- t .start ( ) and
80- result = DataFlow:: importNode ( "invoke.context.Context" )
81- or
82- t .startInAttr ( "Context" ) and
83- result = invoke:: context ( )
84- or
85- // handle invoke.Context alias
86- t .start ( ) and
87- result = invoke_attr ( "Context" )
88- or
89- exists ( DataFlow:: TypeTracker t2 | result = classRef ( t2 ) .track ( t2 , t ) )
32+ API:: Node classRef ( ) {
33+ result =
34+ [ API:: moduleImport ( "invoke" ) .getMember ( "context" ) , API:: moduleImport ( "invoke" ) ]
35+ .getMember ( "Context" )
9036 }
9137
92- /** Gets a reference to the `invoke.context.Context` class. */
93- DataFlow:: Node classRef ( ) { result = classRef ( DataFlow:: TypeTracker:: end ( ) ) }
94-
9538 /** Gets a reference to an instance of `invoke.context.Context`. */
96- private DataFlow:: Node instance ( DataFlow:: TypeTracker t ) {
39+ private DataFlow:: LocalSourceNode instance ( DataFlow:: TypeTracker t ) {
9740 t .start ( ) and
98- result . asCfgNode ( ) . ( CallNode ) . getFunction ( ) =
99- invoke:: context:: Context:: classRef ( ) .asCfgNode ( )
100- or
101- t . start ( ) and
102- exists ( Function func |
103- func . getADecorator ( ) = invoke_attr ( "task" ) . asExpr ( ) and
104- result . ( DataFlow :: ParameterNode ) . getParameter ( ) = func . getArg ( 0 )
41+ (
42+ result = invoke:: context:: Context:: classRef ( ) .getACall ( )
43+ or
44+ exists ( Function func |
45+ func . getADecorator ( ) = invoke ( ) . getMember ( "task" ) . getAUse ( ) . asExpr ( ) and
46+ result . ( DataFlow :: ParameterNode ) . getParameter ( ) = func . getArg ( 0 )
47+ )
10548 )
10649 or
10750 exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
10851 }
10952
11053 /** Gets a reference to an instance of `invoke.context.Context`. */
111- DataFlow:: Node instance ( ) { result = instance ( DataFlow:: TypeTracker:: end ( ) ) }
54+ DataFlow:: LocalSourceNode instance ( ) { result = instance ( DataFlow:: TypeTracker:: end ( ) ) }
11255
11356 /** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
114- private DataFlow:: Node instanceRunMethods ( DataFlow:: TypeTracker t ) {
57+ private DataFlow:: LocalSourceNode instanceRunMethods ( DataFlow:: TypeTracker t ) {
11558 t .startInAttr ( [ "run" , "sudo" ] ) and
11659 result = invoke:: context:: Context:: instance ( )
11760 or
@@ -120,7 +63,7 @@ private module Invoke {
12063
12164 /** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */
12265 DataFlow:: Node instanceRunMethods ( ) {
123- result = instanceRunMethods ( DataFlow:: TypeTracker:: end ( ) )
66+ instanceRunMethods ( DataFlow:: TypeTracker:: end ( ) ) . flowsTo ( result )
12467 }
12568 }
12669 }
@@ -131,15 +74,10 @@ private module Invoke {
13174 * - `invoke.run` or `invoke.sudo` functions (http://docs.pyinvoke.org/en/stable/api/__init__.html)
13275 * - `run` or `sudo` methods on a `invoke.context.Context` instance (http://docs.pyinvoke.org/en/stable/api/context.html#invoke.context.Context.run)
13376 */
134- private class InvokeRunCommandCall extends SystemCommandExecution:: Range , DataFlow:: CfgNode {
135- override CallNode node ;
136-
77+ private class InvokeRunCommandCall extends SystemCommandExecution:: Range , DataFlow:: CallCfgNode {
13778 InvokeRunCommandCall ( ) {
138- exists ( DataFlow:: Node callFunction | node .getFunction ( ) = callFunction .asCfgNode ( ) |
139- callFunction = invoke_attr ( [ "run" , "sudo" ] )
140- or
141- callFunction = invoke:: context:: Context:: instanceRunMethods ( )
142- )
79+ this = invoke ( ) .getMember ( [ "run" , "sudo" ] ) .getACall ( ) or
80+ this .getFunction ( ) = invoke:: context:: Context:: instanceRunMethods ( )
14381 }
14482
14583 override DataFlow:: Node getCommand ( ) {
0 commit comments