@@ -418,7 +418,8 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
418418 let mut initialized = 0 ; // Extra initialized bytes from previous loop iteration
419419 loop {
420420 if buf. len ( ) == buf. capacity ( ) {
421- buf. reserve ( 32 ) ; // buf is full, need more space
421+ // buf is full, need more space
422+ buf. try_reserve ( 32 ) . map_err ( |_| ErrorKind :: OutOfMemory ) ?;
422423 }
423424
424425 let mut spare = buf. spare_capacity_mut ( ) ;
@@ -464,6 +465,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
464465 match r. read ( & mut probe) {
465466 Ok ( 0 ) => return Ok ( buf. len ( ) - start_len) ,
466467 Ok ( n) => {
468+ buf. try_reserve ( n) . map_err ( |_| ErrorKind :: OutOfMemory ) ?;
467469 buf. extend_from_slice ( & probe[ ..n] ) ;
468470 break ;
469471 }
@@ -767,6 +769,30 @@ pub trait Read {
767769 /// file.)
768770 ///
769771 /// [`std::fs::read`]: crate::fs::read
772+ ///
773+ /// ## Implementing `read_to_end`
774+ ///
775+ /// When implementing the `io::Read` trait, it is recommended to allocate
776+ /// memory using [`Vec::try_reserve`]. However, this behavior is not guaranteed
777+ /// by all implementations, and `read_to_end` may not handle out-of-memory
778+ /// situations gracefully.
779+ ///
780+ /// ```no_run
781+ /// # use std::io;
782+ /// # struct Example; impl Example {
783+ /// # fn read_some_data_for_the_example(&self) -> &'static [u8] { &[] }
784+ /// fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
785+ /// let data_read = self.read_some_data_for_the_example();
786+ ///
787+ /// buf.try_reserve(data_read.len()).map_err(|_| io::ErrorKind::OutOfMemory)?;
788+ /// buf.extend_from_slice(data_read);
789+ ///
790+ /// Ok(data_read.len())
791+ /// }
792+ /// # }
793+ /// ```
794+ ///
795+ /// [`Vec::try_reserve`]: crate::vec::Vec::try_reserve
770796 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
771797 fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> Result < usize > {
772798 default_read_to_end ( self , buf, None )
0 commit comments