diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-04-19 19:34:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-19 19:34:58 (GMT) |
commit | 64aa4df8502ca5d0a8ffb767ff97f625625c758c (patch) | |
tree | 7f059f4e132f2b877eb93ae810189d71cff878cb | |
parent | 32c43fbfeeb1502d67e8fb24bb42fcd9b1cc750a (diff) | |
download | cpython-64aa4df8502ca5d0a8ffb767ff97f625625c758c.zip cpython-64aa4df8502ca5d0a8ffb767ff97f625625c758c.tar.gz cpython-64aa4df8502ca5d0a8ffb767ff97f625625c758c.tar.bz2 |
[2.7] bpo-30061: Check if PyObject_Size()/PySequence_Size()/PyMapping_Size() (GH-1096) (GH-1180) (#1183)
raised an error.
(cherry picked from commit bf623ae8843dc30b28c574bec8d29fc14be59d86)
(cherry picked from commit 680fea4)
-rw-r--r-- | Lib/test/test_io.py | 16 | ||||
-rw-r--r-- | Misc/NEWS | 5 | ||||
-rw-r--r-- | Modules/_io/iobase.c | 13 | ||||
-rw-r--r-- | Modules/cjkcodecs/multibytecodec.c | 3 | ||||
-rw-r--r-- | Modules/posixmodule.c | 5 |
5 files changed, 37 insertions, 5 deletions
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index fb91a2d..caca033 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -396,6 +396,22 @@ class IOTest(unittest.TestCase): with self.open(support.TESTFN, "r") as f: self.assertRaises(TypeError, f.readline, 5.3) + def test_readline_nonsizeable(self): + # Issue #30061 + # Crash when readline() returns an object without __len__ + class R(self.IOBase): + def readline(self): + return None + self.assertRaises((TypeError, StopIteration), next, R()) + + def test_next_nonsizeable(self): + # Issue #30061 + # Crash when next() returns an object without __len__ + class R(self.IOBase): + def next(self): + return None + self.assertRaises(TypeError, R().readlines, 1) + def test_raw_bytes_io(self): f = self.BytesIO() self.write_ops(f) @@ -42,6 +42,11 @@ Extension Modules Library ------- +- bpo-30061: Fixed crashes in IOBase methods next() and readlines() when + readline() or next() respectively return non-sizeable object. + Fixed possible other errors caused by not checking results of PyObject_Size(), + PySequence_Size(), or PyMapping_Size(). + - bpo-30011: Fixed race condition in HTMLParser.unescape(). - bpo-30068: _io._IOBase.readlines will check if it's closed first when diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 066dc8e..d813daf 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -571,7 +571,8 @@ iobase_iternext(PyObject *self) if (line == NULL) return NULL; - if (PyObject_Size(line) == 0) { + if (PyObject_Size(line) <= 0) { + /* Error or empty */ Py_DECREF(line); return NULL; } @@ -618,6 +619,7 @@ iobase_readlines(PyObject *self, PyObject *args) } while (1) { + Py_ssize_t line_length; PyObject *line = PyIter_Next(it); if (line == NULL) { if (PyErr_Occurred()) { @@ -631,11 +633,14 @@ iobase_readlines(PyObject *self, PyObject *args) Py_DECREF(line); goto error; } - length += PyObject_Size(line); + line_length = PyObject_Size(line); Py_DECREF(line); - - if (length > hint) + if (line_length < 0) { + goto error; + } + if (line_length > hint - length) break; + length += line_length; } Py_DECREF(it); diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index 8713628..8901b42 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1604,6 +1604,9 @@ mbstreamwriter_writelines(MultibyteStreamWriterObject *self, PyObject *lines) if (r == -1) return NULL; } + /* PySequence_Length() can fail */ + if (PyErr_Occurred()) + return NULL; Py_RETURN_NONE; } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e73805f..ad50536 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6077,7 +6077,7 @@ Set the groups of the current process to list."); static PyObject * posix_setgroups(PyObject *self, PyObject *groups) { - int i, len; + Py_ssize_t i, len; gid_t grouplist[MAX_GROUPS]; if (!PySequence_Check(groups)) { @@ -6085,6 +6085,9 @@ posix_setgroups(PyObject *self, PyObject *groups) return NULL; } len = PySequence_Size(groups); + if (len < 0) { + return NULL; + } if (len > MAX_GROUPS) { PyErr_SetString(PyExc_ValueError, "too many groups"); return NULL; |