File Lib/test/test_capi.py changed (mode: 100644) (index 6e14248a12..a95e4c5280) |
... |
... |
class CAPITest(unittest.TestCase): |
98 |
98 |
def __len__(self): |
def __len__(self): |
99 |
99 |
return 1 |
return 1 |
100 |
100 |
self.assertRaises(TypeError, _posixsubprocess.fork_exec, |
self.assertRaises(TypeError, _posixsubprocess.fork_exec, |
101 |
|
1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17) |
|
|
101 |
|
1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17) |
102 |
102 |
# Issue #15736: overflow in _PySequence_BytesToCharpArray() |
# Issue #15736: overflow in _PySequence_BytesToCharpArray() |
103 |
103 |
class Z(object): |
class Z(object): |
104 |
104 |
def __len__(self): |
def __len__(self): |
|
... |
... |
class CAPITest(unittest.TestCase): |
106 |
106 |
def __getitem__(self, i): |
def __getitem__(self, i): |
107 |
107 |
return b'x' |
return b'x' |
108 |
108 |
self.assertRaises(MemoryError, _posixsubprocess.fork_exec, |
self.assertRaises(MemoryError, _posixsubprocess.fork_exec, |
109 |
|
1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17) |
|
|
109 |
|
1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17) |
110 |
110 |
|
|
111 |
111 |
@unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') |
@unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') |
112 |
112 |
def test_subprocess_fork_exec(self): |
def test_subprocess_fork_exec(self): |
|
... |
... |
class CAPITest(unittest.TestCase): |
116 |
116 |
|
|
117 |
117 |
# Issue #15738: crash in subprocess_fork_exec() |
# Issue #15738: crash in subprocess_fork_exec() |
118 |
118 |
self.assertRaises(TypeError, _posixsubprocess.fork_exec, |
self.assertRaises(TypeError, _posixsubprocess.fork_exec, |
119 |
|
Z(),[b'1'],3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17) |
|
|
119 |
|
Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17) |
120 |
120 |
|
|
121 |
121 |
@unittest.skipIf(MISSING_C_DOCSTRINGS, |
@unittest.skipIf(MISSING_C_DOCSTRINGS, |
122 |
122 |
"Signature information for builtins requires docstrings") |
"Signature information for builtins requires docstrings") |
File Lib/test/test_subprocess.py changed (mode: 100644) (index 8511207f0d..f01bd1a695) |
... |
... |
class POSIXProcessTestCase(BaseTestCase): |
2418 |
2418 |
with self.assertRaises(TypeError): |
with self.assertRaises(TypeError): |
2419 |
2419 |
_posixsubprocess.fork_exec( |
_posixsubprocess.fork_exec( |
2420 |
2420 |
args, exe_list, |
args, exe_list, |
2421 |
|
True, [], cwd, env_list, |
|
|
2421 |
|
True, (), cwd, env_list, |
2422 |
2422 |
-1, -1, -1, -1, |
-1, -1, -1, -1, |
2423 |
2423 |
1, 2, 3, 4, |
1, 2, 3, 4, |
2424 |
2424 |
True, True, func) |
True, True, func) |
|
... |
... |
class POSIXProcessTestCase(BaseTestCase): |
2430 |
2430 |
def test_fork_exec_sorted_fd_sanity_check(self): |
def test_fork_exec_sorted_fd_sanity_check(self): |
2431 |
2431 |
# Issue #23564: sanity check the fork_exec() fds_to_keep sanity check. |
# Issue #23564: sanity check the fork_exec() fds_to_keep sanity check. |
2432 |
2432 |
import _posixsubprocess |
import _posixsubprocess |
|
2433 |
|
class BadInt: |
|
2434 |
|
first = True |
|
2435 |
|
def __init__(self, value): |
|
2436 |
|
self.value = value |
|
2437 |
|
def __int__(self): |
|
2438 |
|
if self.first: |
|
2439 |
|
self.first = False |
|
2440 |
|
return self.value |
|
2441 |
|
raise ValueError |
|
2442 |
|
|
2433 |
2443 |
gc_enabled = gc.isenabled() |
gc_enabled = gc.isenabled() |
2434 |
2444 |
try: |
try: |
2435 |
2445 |
gc.enable() |
gc.enable() |
|
... |
... |
class POSIXProcessTestCase(BaseTestCase): |
2440 |
2450 |
(18, 23, 42, 2**63), # Out of range. |
(18, 23, 42, 2**63), # Out of range. |
2441 |
2451 |
(5, 4), # Not sorted. |
(5, 4), # Not sorted. |
2442 |
2452 |
(6, 7, 7, 8), # Duplicate. |
(6, 7, 7, 8), # Duplicate. |
|
2453 |
|
(BadInt(1), BadInt(2)), |
2443 |
2454 |
): |
): |
2444 |
2455 |
with self.assertRaises( |
with self.assertRaises( |
2445 |
2456 |
ValueError, |
ValueError, |
File Modules/_posixsubprocess.c changed (mode: 100644) (index 5007a39bc2..d1434d59f8) |
... |
... |
_is_fdescfs_mounted_on_dev_fd(void) |
111 |
111 |
static int |
static int |
112 |
112 |
_sanity_check_python_fd_sequence(PyObject *fd_sequence) |
_sanity_check_python_fd_sequence(PyObject *fd_sequence) |
113 |
113 |
{ |
{ |
114 |
|
Py_ssize_t seq_idx, seq_len = PySequence_Length(fd_sequence); |
|
|
114 |
|
Py_ssize_t seq_idx; |
115 |
115 |
long prev_fd = -1; |
long prev_fd = -1; |
116 |
|
for (seq_idx = 0; seq_idx < seq_len; ++seq_idx) { |
|
117 |
|
PyObject* py_fd = PySequence_Fast_GET_ITEM(fd_sequence, seq_idx); |
|
118 |
|
long iter_fd = PyLong_AsLong(py_fd); |
|
|
116 |
|
for (seq_idx = 0; seq_idx < PyTuple_GET_SIZE(fd_sequence); ++seq_idx) { |
|
117 |
|
PyObject* py_fd = PyTuple_GET_ITEM(fd_sequence, seq_idx); |
|
118 |
|
long iter_fd; |
|
119 |
|
if (!PyLong_Check(py_fd)) { |
|
120 |
|
return 1; |
|
121 |
|
} |
|
122 |
|
iter_fd = PyLong_AsLong(py_fd); |
119 |
123 |
if (iter_fd < 0 || iter_fd <= prev_fd || iter_fd > INT_MAX) { |
if (iter_fd < 0 || iter_fd <= prev_fd || iter_fd > INT_MAX) { |
120 |
|
/* Negative, overflow, not a Long, unsorted, too big for a fd. */ |
|
|
124 |
|
/* Negative, overflow, unsorted, too big for a fd. */ |
121 |
125 |
return 1; |
return 1; |
122 |
126 |
} |
} |
123 |
127 |
prev_fd = iter_fd; |
prev_fd = iter_fd; |
|
... |
... |
_is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence) |
132 |
136 |
{ |
{ |
133 |
137 |
/* Binary search. */ |
/* Binary search. */ |
134 |
138 |
Py_ssize_t search_min = 0; |
Py_ssize_t search_min = 0; |
135 |
|
Py_ssize_t search_max = PySequence_Length(fd_sequence) - 1; |
|
|
139 |
|
Py_ssize_t search_max = PyTuple_GET_SIZE(fd_sequence) - 1; |
136 |
140 |
if (search_max < 0) |
if (search_max < 0) |
137 |
141 |
return 0; |
return 0; |
138 |
142 |
do { |
do { |
139 |
143 |
long middle = (search_min + search_max) / 2; |
long middle = (search_min + search_max) / 2; |
140 |
|
long middle_fd = PyLong_AsLong( |
|
141 |
|
PySequence_Fast_GET_ITEM(fd_sequence, middle)); |
|
|
144 |
|
long middle_fd = PyLong_AsLong(PyTuple_GET_ITEM(fd_sequence, middle)); |
142 |
145 |
if (fd == middle_fd) |
if (fd == middle_fd) |
143 |
146 |
return 1; |
return 1; |
144 |
147 |
if (fd > middle_fd) |
if (fd > middle_fd) |
|
... |
... |
make_inheritable(PyObject *py_fds_to_keep, int errpipe_write) |
154 |
157 |
{ |
{ |
155 |
158 |
Py_ssize_t i, len; |
Py_ssize_t i, len; |
156 |
159 |
|
|
157 |
|
len = PySequence_Length(py_fds_to_keep); |
|
|
160 |
|
len = PyTuple_GET_SIZE(py_fds_to_keep); |
158 |
161 |
for (i = 0; i < len; ++i) { |
for (i = 0; i < len; ++i) { |
159 |
|
PyObject* fdobj = PySequence_Fast_GET_ITEM(py_fds_to_keep, i); |
|
|
162 |
|
PyObject* fdobj = PyTuple_GET_ITEM(py_fds_to_keep, i); |
160 |
163 |
long fd = PyLong_AsLong(fdobj); |
long fd = PyLong_AsLong(fdobj); |
161 |
164 |
assert(!PyErr_Occurred()); |
assert(!PyErr_Occurred()); |
162 |
165 |
assert(0 <= fd && fd <= INT_MAX); |
assert(0 <= fd && fd <= INT_MAX); |
|
... |
... |
static void |
213 |
216 |
_close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep) |
_close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep) |
214 |
217 |
{ |
{ |
215 |
218 |
long end_fd = safe_get_max_fd(); |
long end_fd = safe_get_max_fd(); |
216 |
|
Py_ssize_t num_fds_to_keep = PySequence_Length(py_fds_to_keep); |
|
|
219 |
|
Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep); |
217 |
220 |
Py_ssize_t keep_seq_idx; |
Py_ssize_t keep_seq_idx; |
218 |
221 |
int fd_num; |
int fd_num; |
219 |
222 |
/* As py_fds_to_keep is sorted we can loop through the list closing |
/* As py_fds_to_keep is sorted we can loop through the list closing |
220 |
223 |
* fds inbetween any in the keep list falling within our range. */ |
* fds inbetween any in the keep list falling within our range. */ |
221 |
224 |
for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) { |
for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) { |
222 |
|
PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep, |
|
223 |
|
keep_seq_idx); |
|
|
225 |
|
PyObject* py_keep_fd = PyTuple_GET_ITEM(py_fds_to_keep, keep_seq_idx); |
224 |
226 |
int keep_fd = PyLong_AsLong(py_keep_fd); |
int keep_fd = PyLong_AsLong(py_keep_fd); |
225 |
227 |
if (keep_fd < start_fd) |
if (keep_fd < start_fd) |
226 |
228 |
continue; |
continue; |
|
... |
... |
_close_open_fds_safe(int start_fd, PyObject* py_fds_to_keep) |
306 |
308 |
|
|
307 |
309 |
|
|
308 |
310 |
/* Close all open file descriptors from start_fd and higher. |
/* Close all open file descriptors from start_fd and higher. |
309 |
|
* Do not close any in the sorted py_fds_to_keep list. |
|
|
311 |
|
* Do not close any in the sorted py_fds_to_keep tuple. |
310 |
312 |
* |
* |
311 |
313 |
* This function violates the strict use of async signal safe functions. :( |
* This function violates the strict use of async signal safe functions. :( |
312 |
314 |
* It calls opendir(), readdir() and closedir(). Of these, the one most |
* It calls opendir(), readdir() and closedir(). Of these, the one most |
|
... |
... |
subprocess_fork_exec(PyObject* self, PyObject *args) |
562 |
564 |
#endif |
#endif |
563 |
565 |
|
|
564 |
566 |
if (!PyArg_ParseTuple( |
if (!PyArg_ParseTuple( |
565 |
|
args, "OOpOOOiiiiiiiiiiO:fork_exec", |
|
566 |
|
&process_args, &executable_list, &close_fds, &py_fds_to_keep, |
|
|
567 |
|
args, "OOpO!OOiiiiiiiiiiO:fork_exec", |
|
568 |
|
&process_args, &executable_list, |
|
569 |
|
&close_fds, &PyTuple_Type, &py_fds_to_keep, |
567 |
570 |
&cwd_obj, &env_list, |
&cwd_obj, &env_list, |
568 |
571 |
&p2cread, &p2cwrite, &c2pread, &c2pwrite, |
&p2cread, &p2cwrite, &c2pread, &c2pwrite, |
569 |
572 |
&errread, &errwrite, &errpipe_read, &errpipe_write, |
&errread, &errwrite, &errpipe_read, &errpipe_write, |
|
... |
... |
subprocess_fork_exec(PyObject* self, PyObject *args) |
574 |
577 |
PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3"); |
PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3"); |
575 |
578 |
return NULL; |
return NULL; |
576 |
579 |
} |
} |
577 |
|
if (PySequence_Length(py_fds_to_keep) < 0) { |
|
578 |
|
PyErr_SetString(PyExc_ValueError, "cannot get length of fds_to_keep"); |
|
579 |
|
return NULL; |
|
580 |
|
} |
|
581 |
580 |
if (_sanity_check_python_fd_sequence(py_fds_to_keep)) { |
if (_sanity_check_python_fd_sequence(py_fds_to_keep)) { |
582 |
581 |
PyErr_SetString(PyExc_ValueError, "bad value(s) in fds_to_keep"); |
PyErr_SetString(PyExc_ValueError, "bad value(s) in fds_to_keep"); |
583 |
582 |
return NULL; |
return NULL; |
|
... |
... |
subprocess_fork_exec(PyObject* self, PyObject *args) |
631 |
630 |
goto cleanup; |
goto cleanup; |
632 |
631 |
for (arg_num = 0; arg_num < num_args; ++arg_num) { |
for (arg_num = 0; arg_num < num_args; ++arg_num) { |
633 |
632 |
PyObject *borrowed_arg, *converted_arg; |
PyObject *borrowed_arg, *converted_arg; |
|
633 |
|
if (PySequence_Fast_GET_SIZE(fast_args) != num_args) { |
|
634 |
|
PyErr_SetString(PyExc_RuntimeError, "args changed during iteration"); |
|
635 |
|
goto cleanup; |
|
636 |
|
} |
634 |
637 |
borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num); |
borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num); |
635 |
638 |
if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) |
if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) |
636 |
639 |
goto cleanup; |
goto cleanup; |