| #![warn(clippy::uninit_vec)] | |
| use std::cell::UnsafeCell; | |
| use std::mem::MaybeUninit; | |
| #[derive(Default)] | |
| struct MyVec { | |
| vec: Vec<u8>, | |
| } | |
| union MyOwnMaybeUninit { | |
| value: u8, | |
| uninit: (), | |
| } | |
| // https://github.com/rust-lang/rust/issues/119620 | |
| unsafe fn requires_paramenv<S>() { | |
| unsafe { | |
| let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1); | |
| //~^ uninit_vec | |
| vec.set_len(1); | |
| } | |
| let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(2); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(2); | |
| } | |
| } | |
| fn main() { | |
| // with_capacity() -> set_len() should be detected | |
| let mut vec: Vec<u8> = Vec::with_capacity(1000); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(200); | |
| } | |
| // reserve() -> set_len() should be detected | |
| vec.reserve(1000); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(200); | |
| } | |
| // new() -> set_len() should be detected | |
| let mut vec: Vec<u8> = Vec::new(); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(200); | |
| } | |
| // default() -> set_len() should be detected | |
| let mut vec: Vec<u8> = Default::default(); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(200); | |
| } | |
| let mut vec: Vec<u8> = Vec::default(); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(200); | |
| } | |
| // test when both calls are enclosed in the same unsafe block | |
| unsafe { | |
| let mut vec: Vec<u8> = Vec::with_capacity(1000); | |
| //~^ uninit_vec | |
| vec.set_len(200); | |
| vec.reserve(1000); | |
| //~^ uninit_vec | |
| vec.set_len(200); | |
| } | |
| let mut vec: Vec<u8> = Vec::with_capacity(1000); | |
| //~^ uninit_vec | |
| unsafe { | |
| // test the case where there are other statements in the following unsafe block | |
| vec.set_len(200); | |
| assert!(vec.len() == 200); | |
| } | |
| // handle vec stored in the field of a struct | |
| let mut my_vec = MyVec::default(); | |
| my_vec.vec.reserve(1000); | |
| //~^ uninit_vec | |
| unsafe { | |
| my_vec.vec.set_len(200); | |
| } | |
| my_vec.vec = Vec::with_capacity(1000); | |
| //~^ uninit_vec | |
| unsafe { | |
| my_vec.vec.set_len(200); | |
| } | |
| // Test `#[allow(...)]` attributes on inner unsafe block (shouldn't trigger) | |
| let mut vec: Vec<u8> = Vec::with_capacity(1000); | |
| #[allow(clippy::uninit_vec)] | |
| unsafe { | |
| vec.set_len(200); | |
| } | |
| // MaybeUninit-wrapped types should not be detected | |
| unsafe { | |
| let mut vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(1000); | |
| vec.set_len(200); | |
| let mut vec: Vec<(MaybeUninit<u8>, MaybeUninit<bool>)> = Vec::with_capacity(1000); | |
| vec.set_len(200); | |
| let mut vec: Vec<(MaybeUninit<u8>, [MaybeUninit<bool>; 2])> = Vec::with_capacity(1000); | |
| vec.set_len(200); | |
| } | |
| // known false negative | |
| let mut vec1: Vec<u8> = Vec::with_capacity(1000); | |
| let mut vec2: Vec<u8> = Vec::with_capacity(1000); | |
| unsafe { | |
| vec1.set_len(200); | |
| vec2.set_len(200); | |
| } | |
| // set_len(0) should not be detected | |
| let mut vec: Vec<u8> = Vec::with_capacity(1000); | |
| unsafe { | |
| vec.set_len(0); | |
| } | |
| // ZSTs should not be detected | |
| let mut vec: Vec<()> = Vec::with_capacity(1000); | |
| unsafe { | |
| vec.set_len(10); | |
| } | |
| // unions should not be detected | |
| let mut vec: Vec<MyOwnMaybeUninit> = Vec::with_capacity(1000); | |
| unsafe { | |
| vec.set_len(10); | |
| } | |
| polymorphic::<()>(); | |
| fn polymorphic<T>() { | |
| // We are conservative around polymorphic types. | |
| let mut vec: Vec<T> = Vec::with_capacity(1000); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(10); | |
| } | |
| } | |
| fn poly_maybe_uninit<T>() { | |
| // We are conservative around polymorphic types. | |
| let mut vec: Vec<MaybeUninit<T>> = Vec::with_capacity(1000); | |
| unsafe { | |
| vec.set_len(10); | |
| } | |
| } | |
| fn nested_union<T>() { | |
| let mut vec: Vec<UnsafeCell<MaybeUninit<T>>> = Vec::with_capacity(1); | |
| unsafe { | |
| vec.set_len(1); | |
| } | |
| } | |
| struct Recursive<T>(*const Recursive<T>, MaybeUninit<T>); | |
| fn recursive_union<T>() { | |
| // Make sure we don't stack overflow on recursive types. | |
| // The pointer acts as the base case because it can't be uninit regardless of its pointee. | |
| let mut vec: Vec<Recursive<T>> = Vec::with_capacity(1); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(1); | |
| } | |
| } | |
| #[repr(u8)] | |
| enum Enum<T> { | |
| Variant(T), | |
| } | |
| fn union_in_enum<T>() { | |
| // Enums can have a discriminant that can't be uninit, so this should still warn | |
| let mut vec: Vec<Enum<T>> = Vec::with_capacity(1); | |
| //~^ uninit_vec | |
| unsafe { | |
| vec.set_len(1); | |
| } | |
| } | |
| } |