22
33use crate :: ffi:: { CStr , OsStr , OsString } ;
44use crate :: io:: ErrorKind ;
5+ use crate :: mem:: MaybeUninit ;
56use crate :: os:: windows:: ffi:: { OsStrExt , OsStringExt } ;
67use crate :: path:: PathBuf ;
78use crate :: time:: Duration ;
@@ -204,8 +205,8 @@ where
204205 // This initial size also works around `GetFullPathNameW` returning
205206 // incorrect size hints for some short paths:
206207 // https://github.com/dylni/normpath/issues/5
207- let mut stack_buf = [ 0u16 ; 512 ] ;
208- let mut heap_buf = Vec :: new ( ) ;
208+ let mut stack_buf: [ MaybeUninit < u16 > ; 512 ] = MaybeUninit :: uninit_array ( ) ;
209+ let mut heap_buf: Vec < MaybeUninit < u16 > > = Vec :: new ( ) ;
209210 unsafe {
210211 let mut n = stack_buf. len ( ) ;
211212 loop {
@@ -214,6 +215,11 @@ where
214215 } else {
215216 let extra = n - heap_buf. len ( ) ;
216217 heap_buf. reserve ( extra) ;
218+ // We used `reserve` and not `reserve_exact`, so in theory we
219+ // may have gotten more than requested. If so, we'd like to use
220+ // it... so long as we won't cause overflow.
221+ n = heap_buf. capacity ( ) . min ( c:: DWORD :: MAX as usize ) ;
222+ // Safety: MaybeUninit<u16> does not need initialization
217223 heap_buf. set_len ( n) ;
218224 & mut heap_buf[ ..]
219225 } ;
@@ -228,13 +234,13 @@ where
228234 // error" is still 0 then we interpret it as a 0 length buffer and
229235 // not an actual error.
230236 c:: SetLastError ( 0 ) ;
231- let k = match f1 ( buf. as_mut_ptr ( ) , n as c:: DWORD ) {
237+ let k = match f1 ( buf. as_mut_ptr ( ) . cast :: < u16 > ( ) , n as c:: DWORD ) {
232238 0 if c:: GetLastError ( ) == 0 => 0 ,
233239 0 => return Err ( crate :: io:: Error :: last_os_error ( ) ) ,
234240 n => n,
235241 } as usize ;
236242 if k == n && c:: GetLastError ( ) == c:: ERROR_INSUFFICIENT_BUFFER {
237- n *= 2 ;
243+ n = n . saturating_mul ( 2 ) . min ( c :: DWORD :: MAX as usize ) ;
238244 } else if k > n {
239245 n = k;
240246 } else if k == n {
@@ -244,7 +250,9 @@ where
244250 // Therefore k never equals n.
245251 unreachable ! ( ) ;
246252 } else {
247- return Ok ( f2 ( & buf[ ..k] ) ) ;
253+ // Safety: First `k` bytes are initialized.
254+ let slice: & [ u16 ] = MaybeUninit :: slice_assume_init_ref ( & buf[ ..k] ) ;
255+ return Ok ( f2 ( slice) ) ;
248256 }
249257 }
250258 }
0 commit comments