diff --git a/doc/access/BitAccess.md b/doc/access/BitAccess.md index f8b367d0..bea026d5 100644 --- a/doc/access/BitAccess.md +++ b/doc/access/BitAccess.md @@ -12,6 +12,28 @@ traits, but it is a crate-internal item and is not part of the public API. Its blanket implementation for `` prevents any other implementations from being written. +## Implementation and Safety Notes + +This trait is automatically implemented for all types that implement `Radium`, +and relies exclusively on `Radium`’s API and implementations for its work. In +particular, `Radium` has no functions which operate on **pointers**: it +exclusively operates on memory through **references**. Since references must +always refer to initialized memory, `BitAccess` and, by extension, all APIs in +`bitvec` that touch memory, cannot be used to operate on uninitialized memory in +any way. + +While you may *create* a `bitvec` pointer object that targets uninitialized +memory, you may not *dereference* it until the targeted memory has been wholly +initialized with integer values. + +This restriction cannot be loosened without stable access to pointer-based +atomic intrinsics in the Rust standard library and corresponding updates to the +`Radium` trait. + +Do not attempt to access uninitialized memory through `bitvec`. Doing so will +cause `bitvec` to produce references to uninitialized memory, which is undefined +behavior. + [`Radium`]: radium::Radium [`index`]: crate::index [`radium`]: radium diff --git a/doc/ptr/BitPtr.md b/doc/ptr/BitPtr.md index cd105936..4c2c4419 100644 --- a/doc/ptr/BitPtr.md +++ b/doc/ptr/BitPtr.md @@ -33,9 +33,9 @@ crate-internal space optimizations. - `M`: Marks whether the pointer has mutability permissions to the referent memory. Only `Mut` pointers can be used to create `&mut` references. -- `O`: The ordering of bits within a memory element. - `T`: A memory type used to select both the register width and the bus behavior when performing memory accesses. +- `O`: The ordering of bits within a memory element. ## Usage @@ -45,3 +45,17 @@ directly dereferenced, as it is not a pointer; it can only be transformed back into higher referential types, or used in functions that accept it. These pointers can never be null or misaligned. + +## Safety + +Rust and LLVM **do not** have a concept of bit-level initialization yet. +Furthermore, the underlying foundational code that this type uses to manipulate +individual bits in memory relies on construction of **shared references** to +memory, which means that unlike standard pointers, the `T` element to which +`BitPtr` values point must always be **already initialized** in your program +context. + +`bitvec` is not able to detect or enforce this requirement, and is currently not +able to avoid it. See [`BitAccess`] for more information. + +[`BitAccess`]: crate::access::BitAccess diff --git a/doc/vec/BitVec.md b/doc/vec/BitVec.md index ccc53d41..d7a642d6 100644 --- a/doc/vec/BitVec.md +++ b/doc/vec/BitVec.md @@ -146,11 +146,29 @@ useful for client crates to propagate. `` is fastest; `` matches what most debugger views of memory will print, and the rest are documented in the guide. +## Safety + +Unlike the other data structures in this crate, `BitVec` is uniquely able to +hold uninitialized memory and produce pointers into it. As described in the +[`BitAccess`] documentation, this crate is categorically unable to operate on +uninitialized memory in any way. In particular, you may not allocate a buffer +using [`with_capacity()`], then use [`.as_mut_bitptr()`] to create a pointer +used to write into the uninitialized buffer. + +You must always initialize the buffer contents of a `BitVec` before attempting +to view its contents. You can accomplish this through safe APIs such as +`.push()`, `.extend()`, or `.reserve()`. These are all guaranteed to safely +initialize the memory elements underlying the `BitVec` buffer without incurring +undefined behavior in their operation. + [book]: https://bitvecto-rs.github.io/bitvec/type-parameters.html +[`BitAccess`]: crate::access::BitAccess [`BitArray`]: crate::array::BitArray [`BitField`]: crate::field::BitField [`BitSlice`]: crate::slice::BitSlice [`bitvec!`]: macro@crate::bitvec [`std::vector`]: https://en.cppreference.com/w/cpp/container/vector_bool +[`.as_mut_bitptr()`]: crate::slice::BitSlice::as_mut_bitptr [`.get_mut()`]: crate::slice::BitSlice::get_mut [`.set()`]: crate::slice::BitSlice::set +[`::with_capacity()`]: Self::with_capacity diff --git a/src/vec.rs b/src/vec.rs index 7c29b6ad..8d3100b2 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -327,6 +327,36 @@ where unsafe { slice::from_raw_parts_mut(data, len) } } + /// Creates an unsafe shared bit-pointer to the start of the buffer. + /// + /// ## Original + /// + /// [`Vec::as_ptr`](alloc::vec::Vec::as_ptr) + /// + /// ## Safety + /// + /// You must initialize the contents of the underlying buffer before + /// accessing memory through this pointer. See the `BitPtr` documentation + /// for more details. + pub fn as_bitptr(&self) -> BitPtr { + self.bitspan.to_bitptr().to_const() + } + + /// Creates an unsafe writable bit-pointer to the start of the buffer. + /// + /// ## Original + /// + /// [`Vec::as_mut_ptr`](alloc::vec::Vec::as_mut_ptr) + /// + /// ## Safety + /// + /// You must initialize the contents of the underlying buffer before + /// accessing memory through this pointer. See the `BitPtr` documentation + /// for more details. + pub fn as_mut_bitptr(&mut self) -> BitPtr { + self.bitspan.to_bitptr() + } + /// Converts a bit-vector into a boxed bit-slice. /// /// This may cause a reällocation to drop any excess capacity.