Skip to content

Commit 12e4e07

Browse files
committed
Python: Model Python 2 only module popen2
1 parent 8c2f55f commit 12e4e07

File tree

2 files changed

+74
-10
lines changed

2 files changed

+74
-10
lines changed

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,78 @@ private module Stdlib {
339339
)
340340
}
341341
}
342+
343+
// ---------------------------------------------------------------------------
344+
// popen2
345+
// ---------------------------------------------------------------------------
346+
/** Gets a reference to the `popen2` module (only available in Python 2). */
347+
private DataFlow::Node popen2(DataFlow::TypeTracker t) {
348+
t.start() and
349+
result = DataFlow::importModule("popen2")
350+
or
351+
exists(DataFlow::TypeTracker t2 | result = popen2(t2).track(t2, t))
352+
}
353+
354+
/** Gets a reference to the `popen2` module. */
355+
DataFlow::Node popen2() { result = popen2(DataFlow::TypeTracker::end()) }
356+
357+
/**
358+
* Gets a reference to the attribute `attr_name` of the `popen2` module.
359+
* WARNING: Only holds for a few predefined attributes.
360+
*/
361+
private DataFlow::Node popen2_attr(DataFlow::TypeTracker t, string attr_name) {
362+
attr_name in ["popen2", "popen3", "popen4",
363+
// classes
364+
"Popen3", "Popen4"] and
365+
(
366+
t.start() and
367+
result = DataFlow::importMember("popen2", attr_name)
368+
or
369+
t.startInAttr(attr_name) and
370+
result = DataFlow::importModule("popen2")
371+
)
372+
or
373+
// Due to bad performance when using normal setup with `popen2_attr(t2, attr_name).track(t2, t)`
374+
// we have inlined that code and forced a join
375+
exists(DataFlow::TypeTracker t2 |
376+
exists(DataFlow::StepSummary summary |
377+
popen2_attr_first_join(t2, attr_name, result, summary) and
378+
t = t2.append(summary)
379+
)
380+
)
381+
}
382+
383+
pragma[nomagic]
384+
private predicate popen2_attr_first_join(
385+
DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary
386+
) {
387+
DataFlow::StepSummary::step(popen2_attr(t2, attr_name), res, summary)
388+
}
389+
390+
/**
391+
* Gets a reference to the attribute `attr_name` of the `popen2` module.
392+
* WARNING: Only holds for a few predefined attributes.
393+
*/
394+
private DataFlow::Node popen2_attr(string attr_name) {
395+
result = popen2_attr(DataFlow::TypeTracker::end(), attr_name)
396+
}
397+
398+
/**
399+
* A call to any of the `popen.popen*` functions, or instantiation of a `popen.Popen*` class.
400+
* See https://docs.python.org/2.7/library/popen2.html
401+
*/
402+
private class Popen2PopenCall extends SystemCommandExecution::Range {
403+
Popen2PopenCall() {
404+
exists(string name |
405+
name in ["popen2", "popen3", "popen4", "Popen3", "Popen4"] and
406+
this.asCfgNode().(CallNode).getFunction() = popen2_attr(name).asCfgNode()
407+
)
408+
}
409+
410+
override DataFlow::Node getCommand() {
411+
result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0)
412+
or
413+
result.asCfgNode() = this.asCfgNode().(CallNode).getArgByName("cmd")
414+
}
415+
}
342416
}
Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,2 @@
11
| SystemCommandExecution.py:19:31:19:56 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
22
| SystemCommandExecution.py:20:35:20:60 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
3-
| SystemCommandExecution.py:26:30:26:55 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
4-
| SystemCommandExecution.py:27:30:27:55 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
5-
| SystemCommandExecution.py:28:30:28:55 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
6-
| SystemCommandExecution.py:29:30:29:55 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
7-
| SystemCommandExecution.py:30:30:30:55 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
8-
| SystemCommandExecution.py:32:34:32:59 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
9-
| SystemCommandExecution.py:33:34:33:59 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
10-
| SystemCommandExecution.py:34:34:34:59 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
11-
| SystemCommandExecution.py:35:34:35:59 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
12-
| SystemCommandExecution.py:36:34:36:59 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |

0 commit comments

Comments
 (0)