2
2
3
3
use crate :: ffi:: { CStr , OsStr , OsString } ;
4
4
use crate :: io:: ErrorKind ;
5
+ use crate :: mem:: MaybeUninit ;
5
6
use crate :: os:: windows:: ffi:: { OsStrExt , OsStringExt } ;
6
7
use crate :: path:: PathBuf ;
7
8
use crate :: time:: Duration ;
@@ -204,8 +205,8 @@ where
204
205
// This initial size also works around `GetFullPathNameW` returning
205
206
// incorrect size hints for some short paths:
206
207
// 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 ( ) ;
209
210
unsafe {
210
211
let mut n = stack_buf. len ( ) ;
211
212
loop {
@@ -214,6 +215,11 @@ where
214
215
} else {
215
216
let extra = n - heap_buf. len ( ) ;
216
217
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
217
223
heap_buf. set_len ( n) ;
218
224
& mut heap_buf[ ..]
219
225
} ;
@@ -228,13 +234,13 @@ where
228
234
// error" is still 0 then we interpret it as a 0 length buffer and
229
235
// not an actual error.
230
236
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 ) {
232
238
0 if c:: GetLastError ( ) == 0 => 0 ,
233
239
0 => return Err ( crate :: io:: Error :: last_os_error ( ) ) ,
234
240
n => n,
235
241
} as usize ;
236
242
if k == n && c:: GetLastError ( ) == c:: ERROR_INSUFFICIENT_BUFFER {
237
- n *= 2 ;
243
+ n = n . saturating_mul ( 2 ) . min ( c :: DWORD :: MAX as usize ) ;
238
244
} else if k > n {
239
245
n = k;
240
246
} else if k == n {
@@ -244,7 +250,9 @@ where
244
250
// Therefore k never equals n.
245
251
unreachable ! ( ) ;
246
252
} 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) ) ;
248
256
}
249
257
}
250
258
}
0 commit comments