Matrix::new() drops uninitialized memory
https://gitlab.com/dvshapkin/alg-ds/-/blob/a533f2a1520dc1a3688e8bd3a1e7c0b60eb5f3a9/src/ds/matrix.rs#L106-112 https://gitlab.com/dvshapkin/alg-ds/-/blob/a533f2a1520dc1a3688e8bd3a1e7c0b60eb5f3a9/src/ds/matrix.rs#L140-142 # Description `Matrix::new()` internally calls `Matrix::fill_with()` which uses `*ptr = value` pattern to initialize the buffer. This pattern assumes that there is an initialized struct at the address and drops it, which results in dropping of uninitialized struct. # Demonstration * Crate: alg_ds * Version: 0.3.1 * OS: Ubuntu 18.04.5 LTS * Rust: rustc 1.45.2 (d3fb005a3 2020-07-31) * Cargo flags: --release ```rust #![forbid(unsafe_code)] use alg_ds::ds::matrix::Matrix; use std::sync::atomic::{AtomicUsize, Ordering}; static creation_cnt: AtomicUsize = AtomicUsize::new(0); static drop_cnt: AtomicUsize = AtomicUsize::new(0); #[derive(Clone)] struct DropDetector(u32); impl Default for DropDetector { fn default() -> Self { creation_cnt.fetch_add(1, Ordering::Relaxed); DropDetector(12345) } } impl Drop for DropDetector { fn drop(&mut self) { drop_cnt.fetch_add(1, Ordering::Relaxed); println!("Dropping {}", self.0); } } fn main() { // Please check along with the code snippets above. { // `*ptr = value` acts by dropping existing contents at `ptr`. // `Matrix::fill_with()` uses this pattern which result in dropping // uninitialized, unallocated struct. // // Note that the creation of a mutable reference to uninitialized memory // region is already UB by itself. // `ptr::write` and `MaybeUninit` should be used for the initialization. let _ = Matrix::<DropDetector>::new(1, 1); } { // (Bonus) Integer overflow in `layout()` allows to create a huge matrix. // Fortunately, every access to the internal buffer are bound-checked, // so this doesn't lead to obvious UB by itself. let mat = Matrix::<usize>::new(15326306685794188004, 0x123456789); println!( "rows: {}, cols: {}, number of elements: {}", mat.rows(), mat.cols(), mat.elements_number() ); } assert_eq!( creation_cnt.load(Ordering::Relaxed), drop_cnt.load(Ordering::Relaxed) ); } ``` Output: ``` Dropping 0 Dropping 12345 rows: 0, cols: 4886718345, number of elements: 4 thread 'main' panicked at 'assertion failed: `(left == right)` left: `1`, right: `2`', src/main.rs:72:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` Return Code: 101
issue