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

Skip to content

Commit 4e8d2f2

Browse files
committed
asyncio, Tulip issue 130: Add more checks on subprocess_exec/subprocess_shell
parameters
1 parent a125497 commit 4e8d2f2

3 files changed

Lines changed: 64 additions & 7 deletions

File tree

Lib/asyncio/base_events.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ def subprocess_shell(self, protocol_factory, cmd, *, stdin=subprocess.PIPE,
558558
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
559559
universal_newlines=False, shell=True, bufsize=0,
560560
**kwargs):
561-
if not isinstance(cmd, str):
561+
if not isinstance(cmd, (bytes, str)):
562562
raise ValueError("cmd must be a string")
563563
if universal_newlines:
564564
raise ValueError("universal_newlines must be False")
@@ -572,7 +572,7 @@ def subprocess_shell(self, protocol_factory, cmd, *, stdin=subprocess.PIPE,
572572
return transport, protocol
573573

574574
@tasks.coroutine
575-
def subprocess_exec(self, protocol_factory, *args, stdin=subprocess.PIPE,
575+
def subprocess_exec(self, protocol_factory, program, *args, stdin=subprocess.PIPE,
576576
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
577577
universal_newlines=False, shell=False, bufsize=0,
578578
**kwargs):
@@ -582,9 +582,15 @@ def subprocess_exec(self, protocol_factory, *args, stdin=subprocess.PIPE,
582582
raise ValueError("shell must be False")
583583
if bufsize != 0:
584584
raise ValueError("bufsize must be 0")
585+
popen_args = (program,) + args
586+
for arg in popen_args:
587+
if not isinstance(arg, (str, bytes)):
588+
raise TypeError("program arguments must be "
589+
"a bytes or text string, not %s"
590+
% type(arg).__name__)
585591
protocol = protocol_factory()
586592
transport = yield from self._make_subprocess_transport(
587-
protocol, args, False, stdin, stdout, stderr, bufsize, **kwargs)
593+
protocol, popen_args, False, stdin, stdout, stderr, bufsize, **kwargs)
588594
return transport, protocol
589595

590596
def _add_callback(self, handle):

Lib/asyncio/subprocess.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,15 +180,16 @@ def create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None,
180180
return Process(transport, protocol, loop)
181181

182182
@tasks.coroutine
183-
def create_subprocess_exec(*args, stdin=None, stdout=None, stderr=None,
183+
def create_subprocess_exec(program, *args, stdin=None, stdout=None, stderr=None,
184184
loop=None, limit=streams._DEFAULT_LIMIT, **kwds):
185185
if loop is None:
186186
loop = events.get_event_loop()
187187
protocol_factory = lambda: SubprocessStreamProtocol(limit=limit,
188188
loop=loop)
189189
transport, protocol = yield from loop.subprocess_exec(
190190
protocol_factory,
191-
*args, stdin=stdin, stdout=stdout,
191+
program, *args,
192+
stdin=stdin, stdout=stdout,
192193
stderr=stderr, **kwds)
193194
yield from protocol.waiter
194195
return Process(transport, protocol, loop)

Lib/test/test_asyncio/test_base_events.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import errno
44
import logging
55
import socket
6+
import sys
67
import time
78
import unittest
89
import unittest.mock
@@ -234,8 +235,57 @@ def cb(loop):
234235
self.assertEqual([handle], list(self.loop._ready))
235236

236237
def test_run_until_complete_type_error(self):
237-
self.assertRaises(
238-
TypeError, self.loop.run_until_complete, 'blah')
238+
self.assertRaises(TypeError,
239+
self.loop.run_until_complete, 'blah')
240+
241+
def test_subprocess_exec_invalid_args(self):
242+
args = [sys.executable, '-c', 'pass']
243+
244+
# missing program parameter (empty args)
245+
self.assertRaises(TypeError,
246+
self.loop.run_until_complete, self.loop.subprocess_exec,
247+
asyncio.SubprocessProtocol)
248+
249+
# exepected multiple arguments, not a list
250+
self.assertRaises(TypeError,
251+
self.loop.run_until_complete, self.loop.subprocess_exec,
252+
asyncio.SubprocessProtocol, args)
253+
254+
# program arguments must be strings, not int
255+
self.assertRaises(TypeError,
256+
self.loop.run_until_complete, self.loop.subprocess_exec,
257+
asyncio.SubprocessProtocol, sys.executable, 123)
258+
259+
# universal_newlines, shell, bufsize must not be set
260+
self.assertRaises(TypeError,
261+
self.loop.run_until_complete, self.loop.subprocess_exec,
262+
asyncio.SubprocessProtocol, *args, universal_newlines=True)
263+
self.assertRaises(TypeError,
264+
self.loop.run_until_complete, self.loop.subprocess_exec,
265+
asyncio.SubprocessProtocol, *args, shell=True)
266+
self.assertRaises(TypeError,
267+
self.loop.run_until_complete, self.loop.subprocess_exec,
268+
asyncio.SubprocessProtocol, *args, bufsize=4096)
269+
270+
def test_subprocess_shell_invalid_args(self):
271+
# exepected a string, not an int or a list
272+
self.assertRaises(TypeError,
273+
self.loop.run_until_complete, self.loop.subprocess_shell,
274+
asyncio.SubprocessProtocol, 123)
275+
self.assertRaises(TypeError,
276+
self.loop.run_until_complete, self.loop.subprocess_shell,
277+
asyncio.SubprocessProtocol, [sys.executable, '-c', 'pass'])
278+
279+
# universal_newlines, shell, bufsize must not be set
280+
self.assertRaises(TypeError,
281+
self.loop.run_until_complete, self.loop.subprocess_shell,
282+
asyncio.SubprocessProtocol, 'exit 0', universal_newlines=True)
283+
self.assertRaises(TypeError,
284+
self.loop.run_until_complete, self.loop.subprocess_shell,
285+
asyncio.SubprocessProtocol, 'exit 0', shell=True)
286+
self.assertRaises(TypeError,
287+
self.loop.run_until_complete, self.loop.subprocess_shell,
288+
asyncio.SubprocessProtocol, 'exit 0', bufsize=4096)
239289

240290

241291
class MyProto(asyncio.Protocol):

0 commit comments

Comments
 (0)