Last active
November 27, 2019 03:35
-
-
Save eira-fransham/ffa55d8e69377a64c9708e07c2db2a1b to your computer and use it in GitHub Desktop.
Explanation of unsoundness in `SmallVec::insert_many`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate smallvec; | |
use smallvec::SmallVec; | |
struct Printer(usize); | |
impl Drop for Printer { | |
fn drop(&mut self) { | |
println!("Dropping {}", self.0); | |
} | |
} | |
struct Bad; | |
impl Iterator for Bad { | |
type Item = Printer; | |
fn size_hint(&self) -> (usize, Option<usize>) { | |
(1, None) | |
} | |
fn next(&mut self) -> Option<Printer> { | |
panic!() | |
} | |
} | |
// If you run this in the Rust playground this prints: | |
// Dropping 0 | |
// Dropping 0 | |
// Dropping 1 | |
// | |
// Obviously this is fine with this dummy struct but if you | |
// used `Box` this would cause a double-free. | |
// | |
// What happens is that before iterating, | |
// `SmallVec::insert_many` moves the existing elements, so | |
// if you start with an arry that looks like this: | |
// [a, b, c, (uninitialised)] | |
// ^-----^ The elements between these points are at | |
// indexes less than `len` and so can be | |
// accessed. | |
// | |
// You (temporarily) get an array that looks like this: | |
// [a, b, b, c, (uninitialised)] | |
// ^-----^ Accessible elements | |
// | |
// When the iterator panics, the `SmallVec` iterates over | |
// the accessible elements and drops each of them in turn, | |
// which is bad when there are two copies of the same value | |
// (you get a double-drop). | |
fn main() { | |
// This doesn't need to be 0, this is unsound with any | |
// value here. | |
let vec: SmallVec<[Printer; 0]> = vec![ | |
Printer(0), | |
Printer(1), | |
Printer(2), | |
].into(); | |
vec.insert_many(0, Bad); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment