@@ -325,6 +325,32 @@ where
325325 /// previous reallocations did not leave values on the heap.
326326 fn zeroize ( & mut self ) {
327327 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+
328354 self . clear ( ) ;
329355 }
330356}
@@ -458,6 +484,43 @@ mod tests {
458484 assert ! ( vec. is_empty( ) ) ;
459485 }
460486
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+
461524 #[ cfg( feature = "alloc" ) ]
462525 #[ test]
463526 fn zeroize_string ( ) {
0 commit comments