@@ -3,6 +3,9 @@ import semmle.python.dataflow.new.DataFlow
33import semmle.python.dataflow.new.TypeTracker
44import TestUtilities.InlineExpectationsTest
55
6+ // -----------------------------------------------------------------------------
7+ // tracked
8+ // -----------------------------------------------------------------------------
69DataFlow:: Node tracked ( TypeTracker t ) {
710 t .start ( ) and
811 result .asCfgNode ( ) = any ( NameNode n | n .getId ( ) = "tracked" )
@@ -28,6 +31,9 @@ class TrackedTest extends InlineExpectationsTest {
2831 }
2932}
3033
34+ // -----------------------------------------------------------------------------
35+ // int + str
36+ // -----------------------------------------------------------------------------
3137DataFlow:: Node int_type ( TypeTracker t ) {
3238 t .start ( ) and
3339 result .asCfgNode ( ) = any ( CallNode c | c .getFunction ( ) .( NameNode ) .getId ( ) = "int" )
@@ -74,6 +80,9 @@ class TrackedStringTest extends InlineExpectationsTest {
7480 }
7581}
7682
83+ // -----------------------------------------------------------------------------
84+ // tracked_self
85+ // -----------------------------------------------------------------------------
7786DataFlow:: Node tracked_self ( TypeTracker t ) {
7887 t .start ( ) and
7988 exists ( Function f |
@@ -102,3 +111,64 @@ class TrackedSelfTest extends InlineExpectationsTest {
102111 )
103112 }
104113}
114+
115+ // -----------------------------------------------------------------------------
116+ // tracked_foo_bar_baz
117+ // -----------------------------------------------------------------------------
118+ // This modeling follows the same pattern that we currently use in our real library modeling.
119+ /** Gets a reference to `foo` (fictive module). */
120+ private DataFlow:: Node foo ( DataFlow:: TypeTracker t ) {
121+ t .start ( ) and
122+ result = DataFlow:: importNode ( "foo" )
123+ or
124+ exists ( DataFlow:: TypeTracker t2 | result = foo ( t2 ) .track ( t2 , t ) )
125+ }
126+
127+ /** Gets a reference to `foo` (fictive module). */
128+ DataFlow:: Node foo ( ) { result = foo ( DataFlow:: TypeTracker:: end ( ) ) }
129+
130+ /** Gets a reference to `foo.bar` (fictive module). */
131+ private DataFlow:: Node foo_bar ( DataFlow:: TypeTracker t ) {
132+ t .start ( ) and
133+ result = DataFlow:: importNode ( "foo.bar" )
134+ or
135+ t .startInAttr ( "bar" ) and
136+ result = foo ( )
137+ or
138+ exists ( DataFlow:: TypeTracker t2 | result = foo_bar ( t2 ) .track ( t2 , t ) )
139+ }
140+
141+ /** Gets a reference to `foo.bar` (fictive module). */
142+ DataFlow:: Node foo_bar ( ) { result = foo_bar ( DataFlow:: TypeTracker:: end ( ) ) }
143+
144+ /** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
145+ private DataFlow:: Node foo_bar_baz ( DataFlow:: TypeTracker t ) {
146+ t .start ( ) and
147+ result = DataFlow:: importNode ( "foo.bar.baz" )
148+ or
149+ t .startInAttr ( "baz" ) and
150+ result = foo_bar ( )
151+ or
152+ exists ( DataFlow:: TypeTracker t2 | result = foo_bar_baz ( t2 ) .track ( t2 , t ) )
153+ }
154+
155+ /** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
156+ DataFlow:: Node foo_bar_baz ( ) { result = foo_bar_baz ( DataFlow:: TypeTracker:: end ( ) ) }
157+
158+ class TrackedFooBarBaz extends InlineExpectationsTest {
159+ TrackedFooBarBaz ( ) { this = "TrackedFooBarBaz" }
160+
161+ override string getARelevantTag ( ) { result = "tracked_foo_bar_baz" }
162+
163+ override predicate hasActualResult ( Location location , string element , string tag , string value ) {
164+ exists ( DataFlow:: Node e |
165+ e = foo_bar_baz ( ) and
166+ // Module variables have no sensible location, and hence can't be annotated.
167+ not e instanceof DataFlow:: ModuleVariableNode and
168+ tag = "tracked_foo_bar_baz" and
169+ location = e .getLocation ( ) and
170+ value = "" and
171+ element = e .toString ( )
172+ )
173+ }
174+ }
0 commit comments