Skip to content

Commit 6c4fd7c

Browse files
committed
Python: Model Python 2 only platform.popen command execution
1 parent 12e4e07 commit 6c4fd7c

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

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

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,4 +413,73 @@ private module Stdlib {
413413
result.asCfgNode() = this.asCfgNode().(CallNode).getArgByName("cmd")
414414
}
415415
}
416+
417+
// ---------------------------------------------------------------------------
418+
// platform
419+
// ---------------------------------------------------------------------------
420+
/** Gets a reference to the `platform` module. */
421+
private DataFlow::Node platform(DataFlow::TypeTracker t) {
422+
t.start() and
423+
result = DataFlow::importModule("platform")
424+
or
425+
exists(DataFlow::TypeTracker t2 | result = platform(t2).track(t2, t))
426+
}
427+
428+
/** Gets a reference to the `platform` module. */
429+
DataFlow::Node platform() { result = platform(DataFlow::TypeTracker::end()) }
430+
431+
/**
432+
* Gets a reference to the attribute `attr_name` of the `platform` module.
433+
* WARNING: Only holds for a few predefined attributes.
434+
*/
435+
private DataFlow::Node platform_attr(DataFlow::TypeTracker t, string attr_name) {
436+
attr_name in ["popen"] and
437+
(
438+
t.start() and
439+
result = DataFlow::importMember("platform", attr_name)
440+
or
441+
t.startInAttr(attr_name) and
442+
result = DataFlow::importModule("platform")
443+
)
444+
or
445+
// Due to bad performance when using normal setup with `platform_attr(t2, attr_name).track(t2, t)`
446+
// we have inlined that code and forced a join
447+
exists(DataFlow::TypeTracker t2 |
448+
exists(DataFlow::StepSummary summary |
449+
platform_attr_first_join(t2, attr_name, result, summary) and
450+
t = t2.append(summary)
451+
)
452+
)
453+
}
454+
455+
pragma[nomagic]
456+
private predicate platform_attr_first_join(
457+
DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary
458+
) {
459+
DataFlow::StepSummary::step(platform_attr(t2, attr_name), res, summary)
460+
}
461+
462+
/**
463+
* Gets a reference to the attribute `attr_name` of the `platform` module.
464+
* WARNING: Only holds for a few predefined attributes.
465+
*/
466+
private DataFlow::Node platform_attr(string attr_name) {
467+
result = platform_attr(DataFlow::TypeTracker::end(), attr_name)
468+
}
469+
470+
/**
471+
* A call to the `platform.popen` function.
472+
* See https://docs.python.org/2.7/library/platform.html#platform.popen
473+
*/
474+
private class PlatformPopenCall extends SystemCommandExecution::Range {
475+
PlatformPopenCall() {
476+
this.asCfgNode().(CallNode).getFunction() = platform_attr("popen").asCfgNode()
477+
}
478+
479+
override DataFlow::Node getCommand() {
480+
result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0)
481+
or
482+
result.asCfgNode() = this.asCfgNode().(CallNode).getArgByName("cmd")
483+
}
484+
}
416485
}
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
| SystemCommandExecution.py:19:31:19:56 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |
2-
| SystemCommandExecution.py:20:35:20:60 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" |

0 commit comments

Comments
 (0)