diff options
| author | bors <bors@rust-lang.org> | 2024-05-27 14:45:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-05-27 14:45:56 +0000 |
| commit | 79c30b69e4aefaccffcdab8ae70886ef87bf0a43 (patch) | |
| tree | 45f5a4dbd04fea2797846e26920e08dbd26d73db /library/alloc/tests/vec_deque_alloc_error.rs | |
| parent | da6c08e8652d112dc1d44e985842684a4b50bd12 (diff) | |
| parent | 84f70abacb2a9a0d6d90435b44ba69c71147e34c (diff) | |
| download | rust-79c30b69e4aefaccffcdab8ae70886ef87bf0a43.tar.gz rust-79c30b69e4aefaccffcdab8ae70886ef87bf0a43.zip | |
Auto merge of #3635 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'library/alloc/tests/vec_deque_alloc_error.rs')
| -rw-r--r-- | library/alloc/tests/vec_deque_alloc_error.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs new file mode 100644 index 00000000000..c11f4556da9 --- /dev/null +++ b/library/alloc/tests/vec_deque_alloc_error.rs @@ -0,0 +1,49 @@ +#![feature(alloc_error_hook, allocator_api)] + +use std::{ + alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System}, + collections::VecDeque, + panic::{catch_unwind, AssertUnwindSafe}, + ptr::NonNull, +}; + +#[test] +fn test_shrink_to_unwind() { + // This tests that `shrink_to` leaves the deque in a consistent state when + // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369 + // but changed to hopefully not have any UB even if the test fails. + + struct BadAlloc; + + unsafe impl Allocator for BadAlloc { + fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> { + // We allocate zeroed here so that the whole buffer of the deque + // is always initialized. That way, even if the deque is left in + // an inconsistent state, no uninitialized memory should be accessed. + System.allocate_zeroed(l) + } + + unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { + unsafe { System.deallocate(ptr, layout) } + } + + unsafe fn shrink( + &self, + _ptr: NonNull<u8>, + _old_layout: Layout, + _new_layout: Layout, + ) -> Result<NonNull<[u8]>, AllocError> { + Err(AllocError) + } + } + + set_alloc_error_hook(|_| panic!("alloc error")); + + let mut v = VecDeque::with_capacity_in(15, BadAlloc); + v.push_back(1); + v.push_front(2); + // This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds. + assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err()); + // This should only pass if the deque is left in a consistent state. + assert_eq!(v, [2, 1]); +} |
