diff options
| author | Ralf Jung <post@ralfj.de> | 2020-03-08 16:43:03 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2020-03-08 16:43:03 +0100 |
| commit | 528cbc4879ceab332d509e4959fcea8baa7e8b92 (patch) | |
| tree | bde2a13df015b8a6de3406812d37340b4e32b7d5 /src/liballoc | |
| parent | f943349eafaa75a60c05b0c84dcdb771d0eae8c9 (diff) | |
| download | rust-528cbc4879ceab332d509e4959fcea8baa7e8b92.tar.gz rust-528cbc4879ceab332d509e4959fcea8baa7e8b92.zip | |
fix memory leak when vec::IntoIter panics during drop
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/vec.rs | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 61416f2b906..913e261ef12 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2626,13 +2626,21 @@ impl<T: Clone> Clone for IntoIter<T> { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T> Drop for IntoIter<T> { fn drop(&mut self) { + struct DropGuard<'a, T>(&'a mut IntoIter<T>); + + impl<T> Drop for DropGuard<'_, T> { + fn drop(&mut self) { + // RawVec handles deallocation + let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) }; + } + } + + let guard = DropGuard(self); // destroy the remaining elements unsafe { - ptr::drop_in_place(self.as_mut_slice()); + ptr::drop_in_place(guard.0.as_mut_slice()); } - - // RawVec handles deallocation - let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) }; + // now `guard` will be dropped and do the rest } } |
