]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[2.7] bpo-30061: Check if PyObject_Size()/PySequence_Size()/PyMapping_Size() (GH...
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 19 Apr 2017 19:34:58 +0000 (22:34 +0300)
committerGitHub <noreply@github.com>
Wed, 19 Apr 2017 19:34:58 +0000 (22:34 +0300)
raised an error.

(cherry picked from commit bf623ae8843dc30b28c574bec8d29fc14be59d86)
(cherry picked from commit 680fea4)

Lib/test/test_io.py
Misc/NEWS
Modules/_io/iobase.c
Modules/cjkcodecs/multibytecodec.c
Modules/posixmodule.c

index fb91a2dbca410460434e3388f394eea81ae901d0..caca0333e0d82f9447542aab49c8bfd345f5d6e3 100644 (file)
@@ -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)
index f2bd997e5dd503209a5a9c9f059bb7707d44f0eb..29c5e98e3ec6aa6fd7529d5c9af50edd64bbb878 100644 (file)
--- 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
index 066dc8edad6adbb70e7fe99a5eaedaa7eef115d7..d813daf6cfb354e5e0bcc2e9c6d3dc4a4550e4bc 100644 (file)
@@ -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);
index 871362800ef497d3ad5786489412125cff56f38b..8901b42e41e8745ca22511f309d2ad98403f1461 100644 (file)
@@ -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;
 }
index e73805fadfd3e8041ea0c2c7b402c8ef8e4964d2..ad505364bda9da5265ba028d711138b48d4ec688 100644 (file)
@@ -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;