File tree 3 files changed +37
-6
lines changed
3 files changed +37
-6
lines changed Original file line number Diff line number Diff line change 43
43
import _winapi
44
44
except ImportError :
45
45
_winapi = None
46
+ try :
47
+ from _testcapi import INT_MAX
48
+ except ImportError :
49
+ INT_MAX = 2 ** 31 - 1
46
50
47
51
from test .script_helper import assert_python_ok
48
52
@@ -119,6 +123,21 @@ def test_read(self):
119
123
self .assertEqual (type (s ), bytes )
120
124
self .assertEqual (s , b"spam" )
121
125
126
+ def test_large_read (self ):
127
+ with open (support .TESTFN , "wb" ) as fp :
128
+ fp .write (b'test' )
129
+ self .addCleanup (support .unlink , support .TESTFN )
130
+
131
+ # Issue #21932: Make sure that os.read() does not raise an
132
+ # OverflowError for size larger than INT_MAX
133
+ size = INT_MAX + 10
134
+ with open (support .TESTFN , "rb" ) as fp :
135
+ data = os .read (fp .fileno (), size )
136
+
137
+ # The test does not try to read more than 2 GB at once because the
138
+ # operating system is free to return less bytes than requested.
139
+ self .assertEqual (data , b'test' )
140
+
122
141
def test_write (self ):
123
142
# os.write() accepts bytes- and buffer-like objects but not strings
124
143
fd = os .open (support .TESTFN , os .O_CREAT | os .O_WRONLY )
Original file line number Diff line number Diff line change @@ -108,6 +108,11 @@ Core and Builtins
108
108
Library
109
109
-------
110
110
111
+ - Issue #21932: os.read() now uses a :c:func:`Py_ssize_t` type instead of
112
+ :c:type:`int` for the size to support reading more than 2 GB at once. On
113
+ Windows, the size is truncted to INT_MAX. As any call to os.read(), the OS
114
+ may read less bytes than the number of requested bytes.
115
+
111
116
- Issue #21942: Fixed source file viewing in pydoc's server mode on Windows.
112
117
113
118
- Issue #11259: asynchat.async_chat().set_terminator() now raises a ValueError
Original file line number Diff line number Diff line change @@ -7989,24 +7989,31 @@ Read a file descriptor.");
7989
7989
static PyObject *
7990
7990
posix_read (PyObject * self , PyObject * args )
7991
7991
{
7992
- int fd , size ;
7992
+ int fd ;
7993
+ Py_ssize_t size ;
7993
7994
Py_ssize_t n ;
7994
7995
PyObject * buffer ;
7995
- if (!PyArg_ParseTuple (args , "ii :read" , & fd , & size ))
7996
+ if (!PyArg_ParseTuple (args , "in :read" , & fd , & size ))
7996
7997
return NULL ;
7998
+ if (!_PyVerify_fd (fd ))
7999
+ return posix_error ();
8000
+ #ifdef MS_WINDOWS
8001
+ if (size > INT_MAX )
8002
+ size = INT_MAX ;
8003
+ #endif
7997
8004
if (size < 0 ) {
7998
8005
errno = EINVAL ;
7999
8006
return posix_error ();
8000
8007
}
8001
8008
buffer = PyBytes_FromStringAndSize ((char * )NULL , size );
8002
8009
if (buffer == NULL )
8003
8010
return NULL ;
8004
- if (!_PyVerify_fd (fd )) {
8005
- Py_DECREF (buffer );
8006
- return posix_error ();
8007
- }
8008
8011
Py_BEGIN_ALLOW_THREADS
8012
+ #ifdef MS_WINDOWS
8013
+ n = read (fd , PyBytes_AS_STRING (buffer ), (int )size );
8014
+ #else
8009
8015
n = read (fd , PyBytes_AS_STRING (buffer ), size );
8016
+ #endif
8010
8017
Py_END_ALLOW_THREADS
8011
8018
if (n < 0 ) {
8012
8019
Py_DECREF (buffer );
You can’t perform that action at this time.
0 commit comments