@@ -90,7 +90,6 @@ impl StderrForwarder {
9090 }
9191 }
9292
93- #[ allow( clippy:: uninit_vec) ]
9493 fn forward_available ( & mut self ) -> bool {
9594 if let Some ( ( stderr, buffer) ) = self . inner . as_mut ( ) {
9695 loop {
@@ -104,7 +103,7 @@ impl StderrForwarder {
104103 let to_reserve = if self . is_non_blocking && !self . bytes_available_failed {
105104 match crate :: parallel:: stderr:: bytes_available ( stderr) {
106105 #[ cfg( windows) ]
107- Ok ( 0 ) => return false ,
106+ Ok ( 0 ) => break false ,
108107 #[ cfg( unix) ]
109108 Ok ( 0 ) => {
110109 // On Unix, depending on the implementation, we may sometimes get 0 in a
@@ -120,7 +119,7 @@ impl StderrForwarder {
120119 write_warning ( & buffer[ ..] ) ;
121120 }
122121 self . inner = None ;
123- return true ;
122+ break true ;
124123 }
125124 #[ cfg( unix) ]
126125 Err ( _) => {
@@ -137,32 +136,21 @@ impl StderrForwarder {
137136 } ;
138137 buffer. reserve ( to_reserve) ;
139138
140- // SAFETY: 1) the length is set to the capacity, so we are never using memory beyond
141- // the underlying buffer and 2) we always call `truncate` below to set the len back
142- // to the initialized data.
143- unsafe {
144- buffer. set_len ( buffer. capacity ( ) ) ;
145- }
146- match stderr. read ( & mut buffer[ old_data_end..] ) {
139+ // Safety: stderr.read only writes to the spare part of the buffer, it never reads from it
140+ match stderr
141+ . read ( unsafe { & mut * ( buffer. spare_capacity_mut ( ) as * mut _ as * mut [ u8 ] ) } )
142+ {
147143 Err ( err) if err. kind ( ) == std:: io:: ErrorKind :: WouldBlock => {
148144 // No data currently, yield back.
149- buffer. truncate ( old_data_end) ;
150- return false ;
145+ break false ;
151146 }
152147 Err ( err) if err. kind ( ) == std:: io:: ErrorKind :: Interrupted => {
153148 // Interrupted, try again.
154- buffer. truncate ( old_data_end) ;
155- }
156- Ok ( 0 ) | Err ( _) => {
157- // End of stream: flush remaining data and bail.
158- if old_data_end > 0 {
159- write_warning ( & buffer[ ..old_data_end] ) ;
160- }
161- self . inner = None ;
162- return true ;
149+ continue ;
163150 }
164- Ok ( bytes_read) => {
165- buffer. truncate ( old_data_end + bytes_read) ;
151+ Ok ( bytes_read) if bytes_read != 0 => {
152+ // Safety: bytes_read bytes is written to spare part of the buffer
153+ unsafe { buffer. set_len ( old_data_end + bytes_read) } ;
166154 let mut consumed = 0 ;
167155 for line in buffer. split_inclusive ( |& b| b == b'\n' ) {
168156 // Only forward complete lines, leave the rest in the buffer.
@@ -173,6 +161,19 @@ impl StderrForwarder {
173161 }
174162 buffer. drain ( ..consumed) ;
175163 }
164+ res => {
165+ // End of stream: flush remaining data and bail.
166+ if old_data_end > 0 {
167+ write_warning ( & buffer[ ..old_data_end] ) ;
168+ }
169+ if let Err ( err) = res {
170+ write_warning (
171+ format ! ( "Failed to read from child stderr: {err}" ) . as_bytes ( ) ,
172+ ) ;
173+ }
174+ self . inner . take ( ) ;
175+ break true ;
176+ }
176177 }
177178 }
178179 } else {
0 commit comments