@@ -407,8 +407,8 @@ _enter_buffered_busy(buffered *self)
407407
408408#define MINUS_LAST_BLOCK (self , size ) \
409409 (self->buffer_mask ? \
410- (size & ~self->buffer_mask) : \
411- (self->buffer_size * (size / self->buffer_size)))
410+ (( size) & ~self->buffer_mask) : \
411+ (self->buffer_size * (( size) / self->buffer_size)))
412412
413413
414414static int
@@ -1071,6 +1071,7 @@ _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
10711071 }
10721072 _bufferedreader_reset_buf (self );
10731073
1074+ n = Py_MIN (n , self -> buffer_size );
10741075 PyBytesWriter * writer = PyBytesWriter_Create (n );
10751076 if (writer == NULL ) {
10761077 return NULL ;
@@ -1795,25 +1796,32 @@ _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
17951796 * or until an EOF occurs or until read() would block.
17961797 */
17971798static PyObject *
1798- _bufferedreader_read_generic (buffered * self , Py_ssize_t n )
1799+ _bufferedreader_read_generic (buffered * self , Py_ssize_t size )
17991800{
1800- Py_ssize_t current_size , remaining , written ;
1801+ Py_ssize_t current_size , written ;
18011802
18021803 current_size = Py_SAFE_DOWNCAST (READAHEAD (self ), Py_off_t , Py_ssize_t );
1803- if (n <= current_size )
1804- return _bufferedreader_read_fast (self , n );
1804+ if (size <= current_size )
1805+ return _bufferedreader_read_fast (self , size );
18051806
1806- PyBytesWriter * writer = PyBytesWriter_Create (n );
1807+ Py_ssize_t chunksize = self -> buffer_size ;
1808+ if (chunksize < MIN_READ_BUF_SIZE ) {
1809+ chunksize = MINUS_LAST_BLOCK (self , MIN_READ_BUF_SIZE );
1810+ }
1811+ Py_ssize_t allocated = size , resize_after = size ;
1812+ if (size - current_size > chunksize ) {
1813+ allocated = current_size + chunksize ;
1814+ resize_after = allocated - Py_MAX (self -> buffer_size , chunksize /4 );
1815+ }
1816+ PyBytesWriter * writer = PyBytesWriter_Create (allocated );
18071817 if (writer == NULL ) {
18081818 goto error ;
18091819 }
18101820 char * out = PyBytesWriter_GetData (writer );
18111821
1812- remaining = n ;
18131822 written = 0 ;
18141823 if (current_size > 0 ) {
18151824 memcpy (out , self -> buffer + self -> pos , current_size );
1816- remaining -= current_size ;
18171825 written += current_size ;
18181826 self -> pos += current_size ;
18191827 }
@@ -1825,12 +1833,27 @@ _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
18251833 Py_DECREF (r );
18261834 }
18271835 _bufferedreader_reset_buf (self );
1828- while (remaining > 0 ) {
1836+ while (written < size ) {
18291837 /* We want to read a whole block at the end into buffer.
1830- If we had readv() we could do this in one pass. */
1831- Py_ssize_t r = MINUS_LAST_BLOCK (self , remaining );
1832- if (r == 0 )
1838+ If we had readv() we could do this in one pass for the last chunc. */
1839+ if (written > resize_after ) {
1840+ if (size - allocated > chunksize ) {
1841+ allocated += chunksize ;
1842+ resize_after = allocated - Py_MAX (self -> buffer_size , chunksize /4 );
1843+ chunksize += Py_MIN (chunksize , size - allocated - chunksize );
1844+ }
1845+ else {
1846+ resize_after = allocated = size ;
1847+ }
1848+ if (PyBytesWriter_Resize (writer , allocated ) < 0 ) {
1849+ PyBytesWriter_Discard (writer );
1850+ goto error ;
1851+ }
1852+ }
1853+ Py_ssize_t r = MINUS_LAST_BLOCK (self , allocated - written );
1854+ if (r == 0 ) {
18331855 break ;
1856+ }
18341857 r = _bufferedreader_raw_read (self , out + written , r );
18351858 if (r == -1 )
18361859 goto error ;
@@ -1842,13 +1865,19 @@ _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
18421865 PyBytesWriter_Discard (writer );
18431866 Py_RETURN_NONE ;
18441867 }
1845- remaining -= r ;
18461868 written += r ;
18471869 }
1870+ Py_ssize_t remaining = size - written ;
18481871 assert (remaining <= self -> buffer_size );
18491872 self -> pos = 0 ;
18501873 self -> raw_pos = 0 ;
18511874 self -> read_end = 0 ;
1875+ if (allocated < size ) {
1876+ if (PyBytesWriter_Resize (writer , size ) < 0 ) {
1877+ PyBytesWriter_Discard (writer );
1878+ goto error ;
1879+ }
1880+ }
18521881 /* NOTE: when the read is satisfied, we avoid issuing any additional
18531882 reads, which could block indefinitely (e.g. on a socket).
18541883 See issue #9550. */
0 commit comments