Skip to content

Potential soundness issue in bitpacking 0.9.3 #70

@varies-rust

Description

@varies-rust

Hello, and thank you for maintaining this crate.

I found a sanitizer/Miri failure reachable through public crate APIs using safe Rust code. I may be missing crate-specific preconditions, but the behavior looks worth checking because safe callers should not be able to trigger undefined behavior.

Summary

  • Crate: bitpacking
  • Version tested: 0.9.3
  • API paths with similar failures observed:
    • BitPacker1x::num_bits_sorted
    • BitPacker1x::num_bits_strictly_sorted
    • BitPacker4x::num_bits_sorted
    • BitPacker4x::num_bits_strictly_sorted

Observed diagnostics

Miri undefined behavior: error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)

Reproduction

The snippets below are minimal readable reproducers. Each PoC also includes the source location most relevant to the reported failure.

PoC 1: test_bitpacking3::generated_test_3

Relevant source location:

  • src/bitpacker1x.rs:161: the safe wrapper calls UnsafeBitPackerImpl::num_bits_sorted.
  • src/macros_simple.rs:424-438: the unsafe implementation loads a full fixed block from decompressed.

Readable equivalent PoC:

use bitpacking::{BitPacker, BitPacker1x};

#[test]
fn poc() {
    let packer = BitPacker1x::new();
    let short_block: Vec<u32> = Vec::new();

    let _ = packer.num_bits_sorted(0, &short_block);
}

Observed diagnostic:

error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)

Source review and suggested fix

Brief reasoning:

  • The public num_bits path already checks for the exact block length.
  • The sorted variants skip that check and still load a full block from the slice.
  • That makes the length precondition caller-visible through a safe API.

Suggested fix:

  • Validate the exact block length before calling the unsafe routine, or make the precondition explicit in an unsafe API.

Thanks again for taking a look.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions