Skip to content

Commit ede7d8f

Browse files
committed
Python: apply suggestions from code review for asyncio
1 parent 9027eac commit ede7d8f

File tree

1 file changed

+65
-98
lines changed

1 file changed

+65
-98
lines changed

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 65 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -4400,9 +4400,6 @@ private module StdlibPrivate {
44004400
// ---------------------------------------------------------------------------
44014401
// asyncio
44024402
// ---------------------------------------------------------------------------
4403-
/** Gets a reference to the `asyncio` module. */
4404-
API::Node asyncio() { result = API::moduleImport("asyncio") }
4405-
44064403
/** Provides models for the `asyncio` module. */
44074404
module AsyncIO {
44084405
/**
@@ -4411,129 +4408,99 @@ private module StdlibPrivate {
44114408
* See https://docs.python.org/3/library/asyncio-subprocess.html#creating-subprocesses
44124409
*/
44134410
private class CreateSubprocessExec extends SystemCommandExecution::Range,
4414-
FileSystemAccess::Range, DataFlow::CallCfgNode
4411+
FileSystemAccess::Range, API::CallNode
44154412
{
44164413
CreateSubprocessExec() {
4417-
exists(string name |
4418-
name = "create_subprocess_exec" and
4419-
(
4420-
this = asyncio().getMember(name).getACall()
4421-
or
4422-
this = asyncio().getMember("subprocess").getMember(name).getACall()
4423-
)
4424-
)
4425-
}
4426-
4427-
override DataFlow::Node getCommand() {
4428-
result = this.getArg(0)
4414+
this = API::moduleImport("asyncio").getMember("create_subprocess_exec").getACall()
44294415
or
4430-
result = this.getArgByName("program")
4416+
this =
4417+
API::moduleImport("asyncio")
4418+
.getMember("subprocess")
4419+
.getMember("create_subprocess_exec")
4420+
.getACall()
44314421
}
44324422

4423+
override DataFlow::Node getCommand() { result = this.getParameter(0, "program").asSink() }
4424+
44334425
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
44344426

44354427
override predicate isShellInterpreted(DataFlow::Node arg) {
44364428
none() // this is a safe API.
44374429
}
44384430
}
4439-
}
44404431

4441-
/**
4442-
* A call to the `asyncio.create_subprocess_shell` function (also in the `subprocess` module of `asyncio`)
4443-
*
4444-
* See https://docs.python.org/3/library/asyncio-subprocess.html#creating-subprocesses
4445-
*/
4446-
private class CreateSubprocessShell extends SystemCommandExecution::Range,
4447-
FileSystemAccess::Range, DataFlow::CallCfgNode
4448-
{
4449-
CreateSubprocessShell() {
4450-
exists(string name |
4451-
name = "create_subprocess_shell" and
4452-
(
4453-
this = asyncio().getMember(name).getACall()
4454-
or
4455-
this = asyncio().getMember("subprocess").getMember(name).getACall()
4456-
)
4457-
)
4458-
}
4432+
private class CreateSubprocessShell extends SystemCommandExecution::Range,
4433+
FileSystemAccess::Range, API::CallNode
4434+
{
4435+
CreateSubprocessShell() {
4436+
this = API::moduleImport("asyncio").getMember("create_subprocess_shell").getACall()
4437+
or
4438+
this =
4439+
API::moduleImport("asyncio")
4440+
.getMember("subprocess")
4441+
.getMember("create_subprocess_shell")
4442+
.getACall()
4443+
}
44594444

4460-
override DataFlow::Node getCommand() {
4461-
result = this.getArg(0)
4462-
or
4463-
result = this.getArgByName("cmd")
4464-
}
4445+
override DataFlow::Node getCommand() { result = this.getParameter(0, "cmd").asSink() }
44654446

4466-
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
4447+
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
44674448

4468-
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getCommand() }
4469-
}
4449+
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getCommand() }
4450+
}
44704451

4471-
/**
4472-
* A source for an event loop (an object with basetype `AbstractEventLoop`).
4473-
*
4474-
* See https://docs.python.org/3/library/asyncio-eventloop.html
4475-
*/
4476-
private class EventLoopSource extends DataFlow::LocalSourceNode, DataFlow::CallCfgNode {
4477-
EventLoopSource() {
4478-
this = asyncio().getMember("get_running_loop").getACall()
4452+
/**
4453+
* Get an asyncio event loop (an object with basetype `AbstractEventLoop`).
4454+
*
4455+
* See https://docs.python.org/3/library/asyncio-eventloop.html
4456+
*/
4457+
private API::Node getAsyncioEventLoop() {
4458+
result = API::moduleImport("asyncio").getMember("get_running_loop").getReturn()
44794459
or
4480-
this = asyncio().getMember("get_event_loop").getACall() // deprecated in Python 3.10.0 and later
4460+
result = API::moduleImport("asyncio").getMember("get_event_loop").getReturn() // deprecated in Python 3.10.0 and later
44814461
or
4482-
this = asyncio().getMember("new_event_loop").getACall()
4462+
result = API::moduleImport("asyncio").getMember("new_event_loop").getReturn()
44834463
}
4484-
}
4485-
4486-
/** Gets a reference to an event loop instance. */
4487-
private DataFlow::TypeTrackingNode eventLoopInstance(DataFlow::TypeTracker t) {
4488-
t.start() and
4489-
result instanceof EventLoopSource
4490-
or
4491-
exists(DataFlow::TypeTracker t2 | result = eventLoopInstance(t2).track(t2, t))
4492-
}
44934464

4494-
/** Gets a reference to an event loop instance. */
4495-
DataFlow::Node eventLoopInstance() {
4496-
eventLoopInstance(DataFlow::TypeTracker::end()).flowsTo(result)
4497-
}
4498-
4499-
/**
4500-
* A call to `subprocess_exec` on an event loop instance.
4501-
*
4502-
* See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec
4503-
*/
4504-
private class EventLoopSubprocessExec extends DataFlow::MethodCallNode,
4505-
SystemCommandExecution::Range, FileSystemAccess::Range
4506-
{
4507-
EventLoopSubprocessExec() { this.calls(eventLoopInstance(), "subprocess_exec") }
4465+
/**
4466+
* A call to `subprocess_exec` on an event loop instance.
4467+
*
4468+
* See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec
4469+
*/
4470+
private class EventLoopSubprocessExec extends API::CallNode, SystemCommandExecution::Range,
4471+
FileSystemAccess::Range
4472+
{
4473+
EventLoopSubprocessExec() {
4474+
this = getAsyncioEventLoop().getMember("subprocess_exec").getACall()
4475+
}
45084476

4509-
override DataFlow::Node getCommand() { result = this.getArg(1) }
4477+
override DataFlow::Node getCommand() { result = this.getArg(1) }
45104478

4511-
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
4479+
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
45124480

4513-
override predicate isShellInterpreted(DataFlow::Node arg) {
4514-
none() // this is a safe API.
4481+
override predicate isShellInterpreted(DataFlow::Node arg) {
4482+
none() // this is a safe API.
4483+
}
45154484
}
4516-
}
45174485

4518-
/**
4519-
* A call to `subprocess_shell` on an event loop instance.
4520-
*
4521-
* See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_shell
4522-
*/
4523-
private class EventLoopSubprocessShell extends DataFlow::MethodCallNode,
4524-
SystemCommandExecution::Range, FileSystemAccess::Range
4525-
{
4526-
EventLoopSubprocessShell() { this.calls(eventLoopInstance(), "subprocess_shell") }
4486+
/**
4487+
* A call to `subprocess_shell` on an event loop instance.
4488+
*
4489+
* See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_shell
4490+
*/
4491+
private class EventLoopSubprocessShell extends API::CallNode, SystemCommandExecution::Range,
4492+
FileSystemAccess::Range
4493+
{
4494+
EventLoopSubprocessShell() {
4495+
this = getAsyncioEventLoop().getMember("subprocess_shell").getACall()
4496+
}
45274497

4528-
override DataFlow::Node getCommand() {
4529-
result = this.getArg(1)
4530-
or
4531-
result = this.getArgByName("cmd")
4532-
}
4498+
override DataFlow::Node getCommand() { result = this.getParameter(1, "cmd").asSink() }
45334499

4534-
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
4500+
override DataFlow::Node getAPathArgument() { result = this.getCommand() }
45354501

4536-
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getCommand() }
4502+
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getCommand() }
4503+
}
45374504
}
45384505
}
45394506

0 commit comments

Comments
 (0)