Types as Contracts: Implementation and Evaluation

In implementing more validation for miri (namely, ruling out uninitialized data to be passed around at types like u8), I found at least one other contract violation in the standard library. Vec::extend can end up running the following code:

    fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
        let slice = iterator.as_slice();
        self.reserve(slice.len());
        unsafe {
            let len = self.len();
            self.set_len(len + slice.len());
            self.get_unchecked_mut(len..).copy_from_slice(slice); // <-
        }
    }

The interesting line here is the get_unchecked_mut, which creates a slice covering uninitialized data. So this ends up calling copy_from_slice (a safe, public function) with a self argument that is not a valid reference to initialized data. T here can be arbitrary. Imagine T being an enum, then this would pass around (references to) data with an uninitialized discriminant.

None of the exceptions (concerning unsafe code, or private fields) that have been suggested so far would make this legal, nor does there seem to be a good way to fix this locally.

3 Likes