@@ -325,6 +325,32 @@ where
325
325
/// previous reallocations did not leave values on the heap.
326
326
fn zeroize ( & mut self ) {
327
327
self . iter_mut ( ) . zeroize ( ) ;
328
+
329
+ // Zero the capacity of the `Vec` that is not initialized.
330
+ {
331
+ // Safety:
332
+ //
333
+ // This is safe, because `Vec` never allocates more than `isize::MAX` bytes.
334
+ // This exact use case is even mentioned in the documentation of `pointer::add`.
335
+ let extra_capacity_start = unsafe { self . as_mut_ptr ( ) . add ( self . len ( ) ) as * mut u8 } ;
336
+ let extra_capacity_len = self . capacity ( ) . saturating_sub ( self . len ( ) ) ;
337
+
338
+ for i in 0 ..( extra_capacity_len * core:: mem:: size_of :: < Z > ( ) ) {
339
+ // Safety:
340
+ //
341
+ // This is safe, because `Vec` never allocates more than `isize::MAX` bytes.
342
+ let current_ptr = unsafe { extra_capacity_start. add ( i) } ;
343
+ // Safety:
344
+ //
345
+ // `current_ptr` is valid, because it lies within the allocation of the `Vec`.
346
+ // It is also properly aligned, because we write a `u8`, which has an alignment of
347
+ // 1.
348
+ unsafe { ptr:: write_volatile ( current_ptr, 0 ) } ;
349
+ }
350
+
351
+ atomic_fence ( ) ;
352
+ }
353
+
328
354
self . clear ( ) ;
329
355
}
330
356
}
@@ -458,6 +484,43 @@ mod tests {
458
484
assert ! ( vec. is_empty( ) ) ;
459
485
}
460
486
487
+ #[ cfg( feature = "alloc" ) ]
488
+ #[ test]
489
+ fn zeroize_vec_entire_capacity ( ) {
490
+ #[ derive( Clone ) ]
491
+ struct PanicOnNonZeroDrop ( u64 ) ;
492
+
493
+ impl Zeroize for PanicOnNonZeroDrop {
494
+ fn zeroize ( & mut self ) {
495
+ self . 0 = 0 ;
496
+ }
497
+ }
498
+
499
+ impl Drop for PanicOnNonZeroDrop {
500
+ fn drop ( & mut self ) {
501
+ if self . 0 != 0 {
502
+ panic ! ( "dropped non-zeroized data" ) ;
503
+ }
504
+ }
505
+ }
506
+
507
+ // Ensure that the entire capacity of the vec is zeroized and that no unitinialized data
508
+ // is ever interpreted as initialized
509
+ let mut vec = vec ! [ PanicOnNonZeroDrop ( 42 ) ; 2 ] ;
510
+
511
+ unsafe {
512
+ vec. set_len ( 1 ) ;
513
+ }
514
+
515
+ vec. zeroize ( ) ;
516
+
517
+ unsafe {
518
+ vec. set_len ( 2 ) ;
519
+ }
520
+
521
+ drop ( vec) ;
522
+ }
523
+
461
524
#[ cfg( feature = "alloc" ) ]
462
525
#[ test]
463
526
fn zeroize_string ( ) {
0 commit comments