diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2009-03-29 00:45:26 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2009-03-29 00:45:26 (GMT) |
commit | 66994e11544ac8b173ccfedbd05c47082f1dc842 (patch) | |
tree | 8725d34076098548c9f9f0a89a2a063cbaa73168 | |
parent | 24f3629083fc07a31b2e604a94a748f2020585ed (diff) | |
download | cpython-66994e11544ac8b173ccfedbd05c47082f1dc842.zip cpython-66994e11544ac8b173ccfedbd05c47082f1dc842.tar.gz cpython-66994e11544ac8b173ccfedbd05c47082f1dc842.tar.bz2 |
Issue #1174606: Calling read() without arguments of an unbounded file
(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.
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/_fileio.c | 17 |
2 files changed, 17 insertions, 3 deletions
@@ -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. diff --git a/Modules/_fileio.c b/Modules/_fileio.c index 27823b3..6093b40 100644 --- a/Modules/_fileio.c +++ b/Modules/_fileio.c @@ -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) { |