diff -r 6f1602dfa4d5 Include/fileutils.h --- a/Include/fileutils.h Fri Oct 21 19:53:30 2016 +0900 +++ b/Include/fileutils.h Fri Oct 21 16:24:30 2016 +0200 @@ -17,6 +17,14 @@ PyAPI_FUNC(PyObject *) _Py_device_encoding(int); +#if defined(MS_WINDOWS) || defined(__APPLE__) +#define _PY_READ_MAX INT_MAX +#define _PY_WRITE_MAX INT_MAX +#else +#define _PY_READ_MAX PY_SSIZE_T_MAX +#define _PY_WRITE_MAX PY_SSIZE_T_MAX +#endif + #ifdef MS_WINDOWS struct _Py_stat_struct { unsigned long st_dev; diff -r 6f1602dfa4d5 Lib/test/test_largefile.py --- a/Lib/test/test_largefile.py Fri Oct 21 19:53:30 2016 +0900 +++ b/Lib/test/test_largefile.py Fri Oct 21 16:24:30 2016 +0200 @@ -5,6 +5,7 @@ import stat import sys import unittest +from test import support from test.support import TESTFN, requires, unlink import io # C implementation of io import _pyio as pyio # Python implementation of io @@ -16,6 +17,7 @@ """Test that each file function works as expected for large (i.e. > 2GB) files. """ + LARGE = 2**31 def setUp(self): if os.path.exists(TESTFN): @@ -44,6 +46,22 @@ if not os.stat(TESTFN)[stat.ST_SIZE] == 0: raise cls.failureException('File was not truncated by opening ' 'with mode "wb"') + def test_large_writes(self): + support.requires('largefile', + 'test requires %s bytes and a long time to run' % self.LARGE) + with self.open(support.TESTFN, "wb") as f: + b = bytearray(self.LARGE) + self.assertEqual(f.write(b), self.LARGE) + + def test_large_reads(self): + support.requires('largefile', + 'test requires %s bytes and a long time to run' % self.LARGE) + with self.open(support.TESTFN, "wb") as f: + b = bytearray(self.LARGE) + self.assertEqual(f.write(b), self.LARGE) + + with self.open(support.TESTFN, "rb") as f: + self.assertEqual(f.read(self.LARGE), self.LARGE) def test_osstat(self): self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1) diff -r 6f1602dfa4d5 Modules/_io/fileio.c --- a/Modules/_io/fileio.c Fri Oct 21 19:53:30 2016 +0900 +++ b/Modules/_io/fileio.c Fri Oct 21 16:24:30 2016 +0200 @@ -796,11 +796,8 @@ if (size < 0) return _io_FileIO_readall_impl(self); -#ifdef MS_WINDOWS - /* On Windows, the count parameter of read() is an int */ - if (size > INT_MAX) - size = INT_MAX; -#endif + if (size > _PY_READ_MAX) + size = _PY_READ_MAX; bytes = PyBytes_FromStringAndSize(NULL, size); if (bytes == NULL) diff -r 6f1602dfa4d5 Python/fileutils.c --- a/Python/fileutils.c Fri Oct 21 19:53:30 2016 +0900 +++ b/Python/fileutils.c Fri Oct 21 16:24:30 2016 +0200 @@ -1175,18 +1175,9 @@ * handler raised an exception. */ assert(!PyErr_Occurred()); -#ifdef MS_WINDOWS - if (count > INT_MAX) { - /* On Windows, the count parameter of read() is an int */ - count = INT_MAX; + if (count > _PY_READ_MAX) { + count = _PY_READ_MAX; } -#else - if (count > PY_SSIZE_T_MAX) { - /* if count is greater than PY_SSIZE_T_MAX, - * read() result is undefined */ - count = PY_SSIZE_T_MAX; - } -#endif _Py_BEGIN_SUPPRESS_IPH do { @@ -1237,15 +1228,10 @@ depending on heap usage). */ count = 32767; } - else if (count > INT_MAX) - count = INT_MAX; -#else - if (count > PY_SSIZE_T_MAX) { - /* write() should truncate count to PY_SSIZE_T_MAX, but it's safer - * to do it ourself to have a portable behaviour. */ - count = PY_SSIZE_T_MAX; +#endif + if (count > _PY_WRITE_MAX) { + count = _PY_WRITE_MAX; } -#endif if (gil_held) { do {