about summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src
diff options
context:
space:
mode:
authorAlan Egerton <eggyal@gmail.com>2021-11-27 14:19:24 +0000
committerAlan Egerton <eggyal@gmail.com>2021-11-27 15:06:06 +0000
commit04f1c09f90abebd0c6a7658105dec57099a63caa (patch)
treeef324c84b6fe0764a2a9eb7cb955a6ef495ca615 /compiler/rustc_data_structures/src
parent51e15ac7099c00efb425219cf17c8e412d1e14d7 (diff)
downloadrust-04f1c09f90abebd0c6a7658105dec57099a63caa.tar.gz
rust-04f1c09f90abebd0c6a7658105dec57099a63caa.zip
Avoid UB when short-circuiting try_map_id for Vec
Diffstat (limited to 'compiler/rustc_data_structures/src')
-rw-r--r--compiler/rustc_data_structures/src/functor.rs15
1 files changed, 11 insertions, 4 deletions
diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs
index 1307c68ba0b..d3715a998ce 100644
--- a/compiler/rustc_data_structures/src/functor.rs
+++ b/compiler/rustc_data_structures/src/functor.rs
@@ -87,7 +87,6 @@ impl<T> IdFunctor for Vec<T> {
         // FIXME: We don't really care about panics here and leak
         // far more than we should, but that should be fine for now.
         let len = self.len();
-        let mut error = Ok(());
         unsafe {
             self.set_len(0);
             let start = self.as_mut_ptr();
@@ -96,8 +95,16 @@ impl<T> IdFunctor for Vec<T> {
                 match f(ptr::read(p)) {
                     Ok(value) => ptr::write(p, value),
                     Err(err) => {
-                        error = Err(err);
-                        break;
+                        // drop all other elements in self
+                        // (current element was "moved" into the call to f)
+                        for j in (0..i).chain(i + 1..len) {
+                            let p = start.add(j);
+                            ptr::drop_in_place(p);
+                        }
+
+                        // returning will drop self, releasing the allocation
+                        // (len is 0 so elements will not be re-dropped)
+                        return Err(err);
                     }
                 }
             }
@@ -105,7 +112,7 @@ impl<T> IdFunctor for Vec<T> {
             // so we don't leak memory.
             self.set_len(len);
         }
-        error.map(|()| self)
+        Ok(self)
     }
 }