petgraph / fixedbitset

A simple bitset container for Rust
https://docs.rs/fixedbitset/
Apache License 2.0
124 stars 47 forks source link

Undefined Behaviour when dropping `FixedBitSet::into_ones` #111

Closed SkiFire13 closed 7 months ago

SkiFire13 commented 7 months ago

FixedBitSet::into_ones transmutes between Vec with different alignment requirements, which is then UB to drop.

MIRI also reports undefined behaviour in this example:

use fixedbitset::FixedBitSet;

fn main() {
    let mut bitset = FixedBitSet::new();
    bitset.grow(32);
    let iter = bitset.into_ones();
    drop(iter);
}
error: Undefined Behavior: incorrect layout on deallocation: alloc1776 has size 64 and alignment 16, but gave size 64 and alignment 8
   --> E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:119:14
    |
119 |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc1776 has size 64 and alignment 16, but gave size 64 and alignment 8
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:119:14: 119:64
    = note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:256:22: 256:51
    = note: inside `<alloc::raw_vec::RawVec<usize> as std::ops::Drop>::drop` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\raw_vec.rs:555:22: 555:56
    = note: inside `std::ptr::drop_in_place::<alloc::raw_vec::RawVec<usize>> - shim(Some(alloc::raw_vec::RawVec<usize>))` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:515:1: 515:56
    = note: inside `<<std::vec::IntoIter<T, A> as std::ops::Drop>::drop::DropGuard<'_, usize, std::alloc::Global> as std::ops::Drop>::drop` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\vec\into_iter.rs:436:94: 436:95
    = note: inside `std::ptr::drop_in_place::<<std::vec::IntoIter<T, A> as std::ops::Drop>::drop::DropGuard<'_, usize, std::alloc::Global>> - shim(Some(<std::vec::IntoIter<T, A> as std::ops::Drop>::drop::DropGuard<'_, usize, std::alloc::Global>))` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:515:1: 515:56
    = note: inside `<std::vec::IntoIter<usize> as std::ops::Drop>::drop` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\vec\into_iter.rs:447:5: 447:6
    = note: inside `std::ptr::drop_in_place::<std::vec::IntoIter<usize>> - shim(Some(std::vec::IntoIter<usize>))` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:515:1: 515:56
    = note: inside `std::ptr::drop_in_place::<fixedbitset::IntoOnes> - shim(Some(fixedbitset::IntoOnes))` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:515:1: 515:56
    = note: inside `std::mem::drop::<fixedbitset::IntoOnes>` at E:\Programmi\Rust\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\mem\mod.rs:992:24: 992:25
note: inside `main`
   --> src\main.rs:7:5
    |
7   |     drop(iter);
    |     ^^^^^^^^^^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error