@@ -29,7 +29,7 @@ private module Stdlib {
2929 *
3030 * For example, using `attr_name = "system"` will get all uses of `os.system`.
3131 */
32- private DataFlow:: Node os_attr ( string attr_name , DataFlow:: TypeTracker t ) {
32+ private DataFlow:: Node os_attr ( DataFlow:: TypeTracker t , string attr_name ) {
3333 attr_name in [ "system" , "popen" ,
3434 // exec
3535 "execl" , "execle" , "execlp" , "execlpe" , "execv" , "execve" , "execvp" , "execvpe" ,
@@ -41,20 +41,34 @@ private module Stdlib {
4141 result = DataFlow:: importMember ( "os" , attr_name )
4242 or
4343 t .startInAttr ( attr_name ) and
44- result = os ( )
45- or
46- exists ( DataFlow:: TypeTracker t2 | result = os_attr ( attr_name , t2 ) .track ( t2 , t ) )
44+ result = DataFlow:: importModule ( "os" )
45+ )
46+ or
47+ // Due to bad performance when using normal setup with `os_attr(t2, attr_name).track(t2, t)`
48+ // we have inlined that code and forced a join
49+ exists ( DataFlow:: TypeTracker t2 |
50+ exists ( DataFlow:: StepSummary summary |
51+ os_attr_first_join ( t2 , attr_name , result , summary ) and
52+ t = t2 .append ( summary )
53+ )
4754 )
4855 }
4956
57+ pragma [ nomagic]
58+ private predicate os_attr_first_join (
59+ DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res , DataFlow:: StepSummary summary
60+ ) {
61+ DataFlow:: StepSummary:: step ( os_attr ( t2 , attr_name ) , res , summary )
62+ }
63+
5064 /**
5165 * Gets a reference to the attribute `attr_name` of the `os` module.
5266 * WARNING: Only holds for a few predefined attributes.
5367 *
5468 * For example, using `"system"` will get all uses of `os.system`.
5569 */
5670 private DataFlow:: Node os_attr ( string attr_name ) {
57- result = os_attr ( attr_name , DataFlow:: TypeTracker:: end ( ) )
71+ result = os_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
5872 }
5973
6074 /**
@@ -148,27 +162,41 @@ private module Stdlib {
148162 *
149163 * For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`.
150164 */
151- private DataFlow:: Node subprocess_attr ( string attr_name , DataFlow:: TypeTracker t ) {
165+ private DataFlow:: Node subprocess_attr ( DataFlow:: TypeTracker t , string attr_name ) {
152166 attr_name in [ "Popen" , "call" , "check_call" , "check_output" , "run" ] and
153167 (
154168 t .start ( ) and
155169 result = DataFlow:: importMember ( "subprocess" , attr_name )
156170 or
157171 t .startInAttr ( attr_name ) and
158- result = subprocess ( )
159- or
160- exists ( DataFlow:: TypeTracker t2 | result = subprocess_attr ( attr_name , t2 ) .track ( t2 , t ) )
172+ result = DataFlow:: importModule ( "subprocess" )
173+ )
174+ or
175+ // Due to bad performance when using normal setup with `subprocess_attr(t2, attr_name).track(t2, t)`
176+ // we have inlined that code and forced a join
177+ exists ( DataFlow:: TypeTracker t2 |
178+ exists ( DataFlow:: StepSummary summary |
179+ subprocess_attr_first_join ( t2 , attr_name , result , summary ) and
180+ t = t2 .append ( summary )
181+ )
161182 )
162183 }
163184
185+ pragma [ nomagic]
186+ private predicate subprocess_attr_first_join (
187+ DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res , DataFlow:: StepSummary summary
188+ ) {
189+ DataFlow:: StepSummary:: step ( subprocess_attr ( t2 , attr_name ) , res , summary )
190+ }
191+
164192 /**
165193 * Gets a reference to the attribute `attr_name` of the `subprocess` module.
166194 * WARNING: Only holds for a few predefined attributes.
167195 *
168196 * For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`.
169197 */
170198 private DataFlow:: Node subprocess_attr ( string attr_name ) {
171- result = subprocess_attr ( attr_name , DataFlow:: TypeTracker:: end ( ) )
199+ result = subprocess_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
172200 }
173201
174202 /**
0 commit comments