diff options
| author | bors <bors@rust-lang.org> | 2020-03-08 10:51:46 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-03-08 10:51:46 +0000 |
| commit | 1d5241c96208ca7d925442b1a5fa45ad18717a6f (patch) | |
| tree | 3405a2f3f23004a2e1df12fdc22b589b5731b816 /src/liballoc | |
| parent | f943349eafaa75a60c05b0c84dcdb771d0eae8c9 (diff) | |
| parent | 49c82d117084ad0362fee6fb9a524400c1140ce7 (diff) | |
| download | rust-1d5241c96208ca7d925442b1a5fa45ad18717a6f.tar.gz rust-1d5241c96208ca7d925442b1a5fa45ad18717a6f.zip | |
Auto merge of #69822 - Centril:rollup-360ca2j, r=Centril
Rollup of 8 pull requests Successful merges: - #69422 (Remove use of `unwrap()` from save-analysis) - #69548 (Turn trailing tokens in `assert!()` into hard errors) - #69561 (Clean up unstable book) - #69599 (check_binding_alt_eq_ty: improve precision wrt. `if let`) - #69641 (Update books) - #69776 (Fix & test leak of some BTreeMap nodes on panic during `into_iter`) - #69805 (resolve: Modernize some naming) - #69810 (test(bindings_after_at): add dynamic drop tests for bindings_after_at) Failed merges: r? @ghost
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/collections/btree/map.rs | 11 | ||||
| -rw-r--r-- | src/liballoc/tests/btree/map.rs | 26 |
2 files changed, 35 insertions, 2 deletions
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 8b9ffdfb49b..9da324ba2d4 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1477,6 +1477,14 @@ impl<K, V> Drop for IntoIter<K, V> { // Continue the same loop we perform below. This only runs when unwinding, so we // don't have to care about panics this time (they'll abort). while let Some(_) = self.0.next() {} + + // No need to avoid the shared root, because the tree was definitely not empty. + unsafe { + let mut node = ptr::read(&self.0.front).into_node().forget_type(); + while let Some(parent) = node.deallocate_and_ascend() { + node = parent.into_node().forget_type(); + } + } } } @@ -1491,7 +1499,8 @@ impl<K, V> Drop for IntoIter<K, V> { if node.is_shared_root() { return; } - + // Most of the nodes have been deallocated while traversing + // but one pile from a leaf up to the root is left standing. while let Some(parent) = node.deallocate_and_ascend() { node = parent.into_node().forget_type(); } diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index fd07a4d3926..d05eec19346 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -1021,7 +1021,7 @@ fn test_split_off_large_random_sorted() { } #[test] -fn test_into_iter_drop_leak() { +fn test_into_iter_drop_leak_1() { static DROPS: AtomicU32 = AtomicU32::new(0); struct D; @@ -1045,3 +1045,27 @@ fn test_into_iter_drop_leak() { assert_eq!(DROPS.load(Ordering::SeqCst), 5); } + +#[test] +fn test_into_iter_drop_leak_2() { + let size = 12; // to obtain tree with 2 levels (having edges to leaf nodes) + static DROPS: AtomicU32 = AtomicU32::new(0); + static PANIC_POINT: AtomicU32 = AtomicU32::new(0); + + struct D; + impl Drop for D { + fn drop(&mut self) { + if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) { + panic!("panic in `drop`"); + } + } + } + + for panic_point in vec![0, 1, size - 2, size - 1] { + DROPS.store(0, Ordering::SeqCst); + PANIC_POINT.store(panic_point, Ordering::SeqCst); + let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect(); + catch_unwind(move || drop(map.into_iter())).ok(); + assert_eq!(DROPS.load(Ordering::SeqCst), size); + } +} |
