@@ -609,6 +609,25 @@ def readinto(self, b):
609609 with self .assertRaises (ValueError ):
610610 Misbehaved (bad_size ).read ()
611611
612+ def test_RawIOBase_read_gh60107 (self ):
613+ # gh-60107: Ensure a "Raw I/O" which keeps a reference to the
614+ # mutable memory doesn't allow making a mutable bytes.
615+ class RawIOKeepsReference (self .MockRawIOWithoutRead ):
616+ def __init__ (self , * args , ** kwargs ):
617+ self .buf = None
618+ super ().__init__ (* args , ** kwargs )
619+
620+ def readinto (self , buf ):
621+ # buf is the bytearray so keeping a reference to it doesn't keep
622+ # the memory alive; a memoryview does.
623+ self .buf = memoryview (buf )
624+ buf [0 :4 ] = self ._read_stack .pop ()
625+ return 3
626+
627+ with self .assertRaises (BufferError ):
628+ rawio = RawIOKeepsReference ([b"1234" ])
629+ rawio .read (4 )
630+
612631 def test_types_have_dict (self ):
613632 test = (
614633 self .IOBase (),
@@ -724,26 +743,6 @@ def test_RawIOBase_readall(self):
724743 rawio = self .MockRawIOWithoutRead ((b"abc" , b"d" , b"efg" ))
725744 self .assertEqual (rawio .readall (), b"abcdefg" )
726745
727- # gh-60107: Ensure a "Raw I/O" which keeps a reference to the
728- # mutable memory doesn't allow making a mutable bytes.
729- class RawIOKeepsReference (self .MockRawIOWithoutRead ):
730- def __init__ (self , * args , ** kwargs ):
731- self .buf = None
732- super ().__init__ (* args , ** kwargs )
733-
734- def readinto (self , buf ):
735- # buf is the bytearray so keeping a reference to it doesn't keep
736- # the memory alive; a memoryview does.
737- self .buf = memoryview (buf )
738- buf [0 :4 ] = self ._read_stack .pop ()
739- return 3
740-
741- with self .assertRaises (BufferError ):
742- rawio = RawIOKeepsReference ([b"1234" ])
743- rawio .read (4 )
744-
745-
746-
747746 def test_BufferedIOBase_readinto (self ):
748747 # Exercise the default BufferedIOBase.readinto() and readinto1()
749748 # implementations (which call read() or read1() internally).
0 commit comments