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

Skip to content

Commit 149e540

Browse files
committed
(Merge 3.3) Issue #20113: os.readv() and os.writev() now raise an OSError
exception on error instead of returning -1.
2 parents e4314e0 + 57ddf78 commit 149e540

4 files changed

Lines changed: 36 additions & 10 deletions

File tree

Lib/test/test_os.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,11 @@ def test_lseek(self):
12671267
def test_read(self):
12681268
self.check(os.read, 1)
12691269

1270+
@unittest.skipUnless(hasattr(os, 'readv'), 'test needs os.readv()')
1271+
def test_readv(self):
1272+
buf = bytearray(10)
1273+
self.check(os.readv, [buf])
1274+
12701275
@unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()')
12711276
def test_tcsetpgrpt(self):
12721277
self.check(os.tcsetpgrp, 0)
@@ -1275,6 +1280,10 @@ def test_tcsetpgrpt(self):
12751280
def test_write(self):
12761281
self.check(os.write, b" ")
12771282

1283+
@unittest.skipUnless(hasattr(os, 'writev'), 'test needs os.writev()')
1284+
def test_writev(self):
1285+
self.check(os.writev, [b'abc'])
1286+
12781287

12791288
class LinkTests(unittest.TestCase):
12801289
def setUp(self):

Lib/test/test_posix.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,14 @@ def test_utime_nofollow_symlinks(self):
283283
def test_writev(self):
284284
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT)
285285
try:
286-
os.writev(fd, (b'test1', b'tt2', b't3'))
286+
n = os.writev(fd, (b'test1', b'tt2', b't3'))
287+
self.assertEqual(n, 10)
288+
287289
os.lseek(fd, 0, os.SEEK_SET)
288290
self.assertEqual(b'test1tt2t3', posix.read(fd, 10))
291+
292+
# Issue #20113: empty list of buffers should not crash
293+
self.assertEqual(posix.writev(fd, []), 0)
289294
finally:
290295
os.close(fd)
291296

@@ -298,6 +303,9 @@ def test_readv(self):
298303
buf = [bytearray(i) for i in [5, 3, 2]]
299304
self.assertEqual(posix.readv(fd, buf), 10)
300305
self.assertEqual([b'test1', b'tt2', b't3'], [bytes(i) for i in buf])
306+
307+
# Issue #20113: empty list of buffers should not crash
308+
self.assertEqual(posix.readv(fd, []), 0)
301309
finally:
302310
os.close(fd)
303311

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- Issue #20113: os.readv() and os.writev() now raise an OSError exception on
22+
error instead of returning -1.
23+
2124
- Issue #19719: Make importlib.abc.MetaPathFinder.find_module(),
2225
PathEntryFinder.find_loader(), and Loader.load_module() use PEP 451 APIs to
2326
help with backwards-compatibility.

Modules/posixmodule.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8011,14 +8011,14 @@ iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
80118011
*iov = PyMem_New(struct iovec, cnt);
80128012
if (*iov == NULL) {
80138013
PyErr_NoMemory();
8014-
return total;
8014+
return -1;
80158015
}
80168016

80178017
*buf = PyMem_New(Py_buffer, cnt);
80188018
if (*buf == NULL) {
80198019
PyMem_Del(*iov);
80208020
PyErr_NoMemory();
8021-
return total;
8021+
return -1;
80228022
}
80238023

80248024
for (i = 0; i < cnt; i++) {
@@ -8043,7 +8043,7 @@ iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
80438043
PyBuffer_Release(&(*buf)[j]);
80448044
}
80458045
PyMem_Del(*buf);
8046-
return 0;
8046+
return -1;
80478047
}
80488048

80498049
static void
@@ -8083,14 +8083,17 @@ posix_readv(PyObject *self, PyObject *args)
80838083
}
80848084
cnt = PySequence_Size(seq);
80858085

8086-
if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE))
8086+
if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0)
80878087
return NULL;
80888088

80898089
Py_BEGIN_ALLOW_THREADS
80908090
n = readv(fd, iov, cnt);
80918091
Py_END_ALLOW_THREADS
80928092

80938093
iov_cleanup(iov, buf, cnt);
8094+
if (n < 0)
8095+
return posix_error();
8096+
80948097
return PyLong_FromSsize_t(n);
80958098
}
80968099
#endif
@@ -8216,8 +8219,8 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
82168219
Py_ssize_t i = 0; /* Avoid uninitialized warning */
82178220
sf.hdr_cnt = PySequence_Size(headers);
82188221
if (sf.hdr_cnt > 0 &&
8219-
!(i = iov_setup(&(sf.headers), &hbuf,
8220-
headers, sf.hdr_cnt, PyBUF_SIMPLE)))
8222+
(i = iov_setup(&(sf.headers), &hbuf,
8223+
headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
82218224
return NULL;
82228225
#ifdef __APPLE__
82238226
sbytes += i;
@@ -8233,8 +8236,8 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
82338236
Py_ssize_t i = 0; /* Avoid uninitialized warning */
82348237
sf.trl_cnt = PySequence_Size(trailers);
82358238
if (sf.trl_cnt > 0 &&
8236-
!(i = iov_setup(&(sf.trailers), &tbuf,
8237-
trailers, sf.trl_cnt, PyBUF_SIMPLE)))
8239+
(i = iov_setup(&(sf.trailers), &tbuf,
8240+
trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
82388241
return NULL;
82398242
#ifdef __APPLE__
82408243
sbytes += i;
@@ -8475,7 +8478,7 @@ posix_writev(PyObject *self, PyObject *args)
84758478
}
84768479
cnt = PySequence_Size(seq);
84778480

8478-
if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) {
8481+
if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) {
84798482
return NULL;
84808483
}
84818484

@@ -8484,6 +8487,9 @@ posix_writev(PyObject *self, PyObject *args)
84848487
Py_END_ALLOW_THREADS
84858488

84868489
iov_cleanup(iov, buf, cnt);
8490+
if (res < 0)
8491+
return posix_error();
8492+
84878493
return PyLong_FromSsize_t(res);
84888494
}
84898495
#endif

0 commit comments

Comments
 (0)