@@ -430,6 +430,8 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
430
430
loop {
431
431
match r. read ( & mut probe) {
432
432
Ok ( n) => {
433
+ // there is no way to recover from allocation failure here
434
+ // because the data has already been read.
433
435
buf. extend_from_slice ( & probe[ ..n] ) ;
434
436
return Ok ( n) ;
435
437
}
@@ -462,7 +464,8 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
462
464
}
463
465
464
466
if buf. len ( ) == buf. capacity ( ) {
465
- buf. reserve ( PROBE_SIZE ) ; // buf is full, need more space
467
+ // buf is full, need more space
468
+ buf. try_reserve ( PROBE_SIZE ) . map_err ( |_| ErrorKind :: OutOfMemory ) ?;
466
469
}
467
470
468
471
let mut spare = buf. spare_capacity_mut ( ) ;
@@ -815,6 +818,39 @@ pub trait Read {
815
818
/// file.)
816
819
///
817
820
/// [`std::fs::read`]: crate::fs::read
821
+ ///
822
+ /// ## Implementing `read_to_end`
823
+ ///
824
+ /// When implementing the `io::Read` trait, it is recommended to allocate
825
+ /// memory using [`Vec::try_reserve`]. However, this behavior is not guaranteed
826
+ /// by all implementations, and `read_to_end` may not handle out-of-memory
827
+ /// situations gracefully.
828
+ ///
829
+ /// ```no_run
830
+ /// # use std::io::{self, BufRead};
831
+ /// # struct Example { example_datasource: io::Empty } impl Example {
832
+ /// # fn get_some_data_for_the_example(&self) -> &'static [u8] { &[] }
833
+ /// fn read_to_end(&mut self, dest_vec: &mut Vec<u8>) -> io::Result<usize> {
834
+ /// let initial_vec_len = dest_vec.len();
835
+ /// loop {
836
+ /// let src_buf = self.example_datasource.fill_buf()?;
837
+ /// if src_buf.is_empty() {
838
+ /// break;
839
+ /// }
840
+ /// dest_vec.try_reserve(src_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?;
841
+ /// dest_vec.extend_from_slice(src_buf);
842
+ ///
843
+ /// // Any irreversible side effects should happen after `try_reserve` succeeds,
844
+ /// // to avoid losing data on allocation error.
845
+ /// let read = src_buf.len();
846
+ /// self.example_datasource.consume(read);
847
+ /// }
848
+ /// Ok(dest_vec.len() - initial_vec_len)
849
+ /// }
850
+ /// # }
851
+ /// ```
852
+ ///
853
+ /// [`Vec::try_reserve`]: crate::vec::Vec::try_reserve
818
854
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
819
855
fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> Result < usize > {
820
856
default_read_to_end ( self , buf, None )
0 commit comments