Skip to content

Commit

Permalink
Zero vector contents after popping
Browse files Browse the repository at this point in the history
Since Alloy is a conservative GC, this prevents memory leaks kept alive
by stale vector elements.
  • Loading branch information
jacob-hughes committed Sep 14, 2023
1 parent edd8099 commit e6c7ce1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
4 changes: 3 additions & 1 deletion library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1955,7 +1955,9 @@ impl<T, A: Allocator> Vec<T, A> {
} else {
unsafe {
self.len -= 1;
Some(ptr::read(self.as_ptr().add(self.len())))
let value = Some(ptr::read(self.as_ptr().add(self.len())));
ptr::write_bytes(self.as_mut_ptr().add(self.len()), 0, 1);
value
}
}
}
Expand Down
45 changes: 45 additions & 0 deletions tests/ui/runtime/gc/zero_vecs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// run-pass
// ignore-tidy-linelength
#![feature(gc)]
#![feature(rustc_private)]
#![feature(negative_impls)]
#![feature(allocator_api)]
#![allow(unused_assignments)]
#![allow(unused_variables)]

use std::gc::{Gc, GcAllocator};
use std::sync::atomic::{self, AtomicUsize};

struct Finalizable(usize);

impl Drop for Finalizable {
fn drop(&mut self) {
FINALIZER_COUNT.fetch_add(1, atomic::Ordering::Relaxed);
}
}

static FINALIZER_COUNT: AtomicUsize = AtomicUsize::new(0);

fn test_pop(v: &mut Vec<Gc<Finalizable>, GcAllocator>) {
for i in 0..10 {
let mut gc = Some(Gc::new(Finalizable(i)));
v.push(gc.unwrap());
gc = None;
}

for _ in 0..10 {
let mut _gc = Some(v.pop());
_gc = None;
}
}

fn main() {
let mut v1 = Vec::with_capacity_in(10, GcAllocator);
test_pop(&mut v1);
test_pop(&mut v1);

GcAllocator::force_gc();

assert_eq!(FINALIZER_COUNT.load(atomic::Ordering::Relaxed), 20);

}

0 comments on commit e6c7ce1

Please sign in to comment.