Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c4a2e1d

Browse files
committed
Python: Rewrite attribute lookup helpers for better performance
Not that they actually had a huge problem right now, just that using the old pattern HAS lead to bad performance in the past. See #4361
1 parent 4adc26e commit c4a2e1d

1 file changed

Lines changed: 38 additions & 10 deletions

File tree

  • python/ql/src/experimental/semmle/python/frameworks

python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)