]> granicus.if.org Git - python/commitdiff
Issue #1174606: Calling read() without arguments of an unbounded file
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 29 Mar 2009 00:45:26 +0000 (00:45 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 29 Mar 2009 00:45:26 +0000 (00:45 +0000)
(typically /dev/zero under Unix) could crash the interpreter.

No test as there always seems to be a risk of putting the machine on its knees.

Misc/NEWS
Modules/_fileio.c

index ccc09cf0d7ae0e8bf135c7be80b23f45344f5c6f..c6f9594170c15c4244c1f457d377261d8c0ab389 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -43,6 +43,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #1174606: Calling read() without arguments of an unbounded file
+  (typically /dev/zero under Unix) could crash the interpreter.
+
 - The max_buffer_size arguments of io.BufferedWriter, io.BufferedRWPair, and
   io.BufferedRandom have been deprecated for removal in Python 3.2.
 
index 27823b3d4e7ff7034fb310a54043fb31c3e6ac76..6093b4064ca4a867c5a9ae91cedb85250ce8b1d1 100644 (file)
@@ -502,9 +502,14 @@ new_buffersize(PyFileIOObject *self, size_t currentsize)
        if (fstat(self->fd, &st) == 0) {
                end = st.st_size;
                pos = lseek(self->fd, 0L, SEEK_CUR);
-               if (end >= pos && pos >= 0)
+               /* Files claiming a size smaller than SMALLCHUNK may
+                  actually be streaming pseudo-files. In this case, we
+                  apply the more aggressive algorithm below.
+               */
+               if (end >= SMALLCHUNK && pos >= 0) {
+                       /* Add 1 so if the file were to grow we'd notice. */
                        return currentsize + end - pos + 1;
-               /* Add 1 so if the file were to grow we'd notice. */
+               }
        }
 #endif
        if (currentsize > SMALLCHUNK) {
@@ -533,7 +538,13 @@ fileio_readall(PyFileIOObject *self)
                return NULL;
 
        while (1) {
-               Py_ssize_t newsize = new_buffersize(self, total);
+               size_t newsize = new_buffersize(self, total);
+               if (newsize > PY_SSIZE_T_MAX || newsize <= 0) {
+                       PyErr_SetString(PyExc_OverflowError,
+                               "unbounded read returned more bytes "
+                               "than a Python string can hold ");
+                       return NULL;
+               }
 
                if (PyBytes_GET_SIZE(result) < newsize) {
                        if (_PyBytes_Resize(&result, newsize) < 0) {