Index: Objects/fileobject.c =================================================================== --- Objects/fileobject.c (revision 62996) +++ Objects/fileobject.c (working copy) @@ -864,6 +864,12 @@ off_t pos, end; struct stat st; if (fstat(fileno(f->f_fp), &st) == 0) { + /* if this isn't a regular file, then we can't trust st_size; in this + * case, return a very large number that will trigger an OverflowError + * in file_read; users must specify a buffer length in this case. */ + if (!S_ISREG(st.st_mode)) + return PY_SSIZE_T_MAX+1; + end = st.st_size; /* The following is not a bug: we really need to call lseek() *and* ftell(). The reason is that some stdio libraries @@ -966,6 +972,11 @@ } if (bytesrequested < 0) { buffersize = new_buffersize(f, buffersize); + if (buffersize > PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unbounded read consumed more bytes than a Python string can hold"); + return NULL; + } if (_PyString_Resize(&v, buffersize) < 0) return NULL; } else { Index: Lib/test/test_file.py =================================================================== --- Lib/test/test_file.py (revision 62996) +++ Lib/test/test_file.py (working copy) @@ -134,6 +134,20 @@ f.close() self.fail('%r is an invalid file mode' % mode) + def testDevZeroOverflow(self): + # /dev/zero is highly efficient at reading an unbounded number + # of bytes in modern linux kernels. This unbounded reading from + # /dev/zero to not result in a MemoryError but instead trigger a + # OverflowError + if not os.path.exists('/dev/zero'): + return + try: + open('/dev/zero').read() + assert(0, + 'Reading from /dev/zero unexpectedly returned successfully') + except OverflowError, err: + self.assertEquals(str(err), 'requested number of bytes is more than a Python string can hold') + def testStdin(self): # This causes the interpreter to exit on OSF1 v5.1. if sys.platform != 'osf1V5':