summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_fileio.c17
2 files changed, 17 insertions, 3 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index ccc09cf..c6f9594 100644
--- 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.
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) {