@@ -4396,6 +4396,117 @@ private module StdlibPrivate {
43964396 preservesValue = true
43974397 }
43984398 }
4399+
4400+ // ---------------------------------------------------------------------------
4401+ // asyncio
4402+ // ---------------------------------------------------------------------------
4403+ /** Provides models for the `asyncio` module. */
4404+ module AsyncIO {
4405+ /**
4406+ * A call to the `asyncio.create_subprocess_exec` function (also accessible via the `subprocess` module of `asyncio`)
4407+ *
4408+ * See https://docs.python.org/3/library/asyncio-subprocess.html#creating-subprocesses
4409+ */
4410+ private class CreateSubprocessExec extends SystemCommandExecution:: Range ,
4411+ FileSystemAccess:: Range , API:: CallNode
4412+ {
4413+ CreateSubprocessExec ( ) {
4414+ this = API:: moduleImport ( "asyncio" ) .getMember ( "create_subprocess_exec" ) .getACall ( )
4415+ or
4416+ this =
4417+ API:: moduleImport ( "asyncio" )
4418+ .getMember ( "subprocess" )
4419+ .getMember ( "create_subprocess_exec" )
4420+ .getACall ( )
4421+ }
4422+
4423+ override DataFlow:: Node getCommand ( ) { result = this .getParameter ( 0 , "program" ) .asSink ( ) }
4424+
4425+ override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
4426+
4427+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
4428+ none ( ) // this is a safe API.
4429+ }
4430+ }
4431+
4432+ /**
4433+ * A call to the `asyncio.create_subprocess_shell` function (also accessible via the `subprocess` module of `asyncio`)
4434+ *
4435+ * See https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.create_subprocess_shell
4436+ */
4437+ private class CreateSubprocessShell extends SystemCommandExecution:: Range ,
4438+ FileSystemAccess:: Range , API:: CallNode
4439+ {
4440+ CreateSubprocessShell ( ) {
4441+ this = API:: moduleImport ( "asyncio" ) .getMember ( "create_subprocess_shell" ) .getACall ( )
4442+ or
4443+ this =
4444+ API:: moduleImport ( "asyncio" )
4445+ .getMember ( "subprocess" )
4446+ .getMember ( "create_subprocess_shell" )
4447+ .getACall ( )
4448+ }
4449+
4450+ override DataFlow:: Node getCommand ( ) { result = this .getParameter ( 0 , "cmd" ) .asSink ( ) }
4451+
4452+ override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
4453+
4454+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
4455+ }
4456+
4457+ /**
4458+ * Get an asyncio event loop (an object with basetype `AbstractEventLoop`).
4459+ *
4460+ * See https://docs.python.org/3/library/asyncio-eventloop.html
4461+ */
4462+ private API:: Node getAsyncioEventLoop ( ) {
4463+ result = API:: moduleImport ( "asyncio" ) .getMember ( "get_running_loop" ) .getReturn ( )
4464+ or
4465+ result = API:: moduleImport ( "asyncio" ) .getMember ( "get_event_loop" ) .getReturn ( ) // deprecated in Python 3.10.0 and later
4466+ or
4467+ result = API:: moduleImport ( "asyncio" ) .getMember ( "new_event_loop" ) .getReturn ( )
4468+ }
4469+
4470+ /**
4471+ * A call to `subprocess_exec` on an event loop instance.
4472+ *
4473+ * See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_exec
4474+ */
4475+ private class EventLoopSubprocessExec extends API:: CallNode , SystemCommandExecution:: Range ,
4476+ FileSystemAccess:: Range
4477+ {
4478+ EventLoopSubprocessExec ( ) {
4479+ this = getAsyncioEventLoop ( ) .getMember ( "subprocess_exec" ) .getACall ( )
4480+ }
4481+
4482+ override DataFlow:: Node getCommand ( ) { result = this .getArg ( 1 ) }
4483+
4484+ override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
4485+
4486+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
4487+ none ( ) // this is a safe API.
4488+ }
4489+ }
4490+
4491+ /**
4492+ * A call to `subprocess_shell` on an event loop instance.
4493+ *
4494+ * See https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.subprocess_shell
4495+ */
4496+ private class EventLoopSubprocessShell extends API:: CallNode , SystemCommandExecution:: Range ,
4497+ FileSystemAccess:: Range
4498+ {
4499+ EventLoopSubprocessShell ( ) {
4500+ this = getAsyncioEventLoop ( ) .getMember ( "subprocess_shell" ) .getACall ( )
4501+ }
4502+
4503+ override DataFlow:: Node getCommand ( ) { result = this .getParameter ( 1 , "cmd" ) .asSink ( ) }
4504+
4505+ override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
4506+
4507+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
4508+ }
4509+ }
43994510}
44004511
44014512// ---------------------------------------------------------------------------
0 commit comments