summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2017-04-19 19:34:58 (GMT)
committerGitHub <noreply@github.com>2017-04-19 19:34:58 (GMT)
commit64aa4df8502ca5d0a8ffb767ff97f625625c758c (patch)
tree7f059f4e132f2b877eb93ae810189d71cff878cb
parent32c43fbfeeb1502d67e8fb24bb42fcd9b1cc750a (diff)
downloadcpython-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.py16
-rw-r--r--Misc/NEWS5
-rw-r--r--Modules/_io/iobase.c13
-rw-r--r--Modules/cjkcodecs/multibytecodec.c3
-rw-r--r--Modules/posixmodule.c5
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)
diff --git a/Misc/NEWS b/Misc/NEWS
index f2bd997..29c5e98 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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;