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 23:38:02 2016 +0200 @@ -17,6 +17,17 @@ PyAPI_FUNC(PyObject *) _Py_device_encoding(int); +#if defined(MS_WINDOWS) || defined(__APPLE__) +/* On Windows, the count parameter of read() is an int + See issue #24658 +*/ +#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 23:38:02 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,7 +17,6 @@ """Test that each file function works as expected for large (i.e. > 2GB) files. """ - def setUp(self): if os.path.exists(TESTFN): mode = 'r+b' @@ -45,6 +45,18 @@ raise cls.failureException('File was not truncated by opening ' 'with mode "wb"') + def test_large_reads_writes(self): + # see issue #24658 + support.requires('largefile', + 'test requires %s bytes and a long time to run' % size) + with self.open(support.TESTFN, "wb") as f: + b = b'x' * size + self.assertEqual(f.write(b), size) + + with self.open(support.TESTFN, "rb") as f: + self.assertEqual(f.read(size), size) + self.assertEqual(f.tell(), size) + 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 23:38:02 2016 +0200 @@ -796,11 +796,9 @@ 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 23:38:02 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 {