Skip to content

Potential unsoundness in PrimitiveElement (bool::get) reachable from safe Rust #618

@varies-rust

Description

@varies-rust

Hi, thanks for your work on this type system.

Our analysis tool flagged a potential unsoundness in capnp::private::layout::PrimitiveElement (specifically the bool implementation) , where a memory violation (null pointer dereference) appears reachable from safe Rust. I’m not fully familiar with the internal invariants of this module, so I’d like to ask maintainers to help confirm whether this is an actual issue.

Concrete PoC:

extern crate capnp;
fn test_function58() -> Option<()> {
    let _local0 = capnp::private::layout::StructReader::<'_>::new_default();
    let _local1 = capnp::private::layout::StructReader::<'_>::get_pointer_section_as_list(&_local0);
    let _local2 = capnp::data_list::Reader::<'_>::new(_local1);
    let _local3 = <capnp::data_list::Reader::<'_> as capnp::traits::IntoInternalListReader::<'_>>::into_internal_list_reader(_local2);
    let _local4 = capnp::private::layout::ListReader::<'_>::new_default();
    let _local5 = capnp::private::layout::ListReader::<'_>::len(&_local4);
    let _ = <bool as capnp::private::layout::PrimitiveElement>::get(&_local3, _local5);
    Some(())
}
#[test]
fn test_58_miri() {
    test_function58();
}

Condensed Miri report:

error: Undefined Behavior: memory access failed: attempting to access 1 byte, but got null pointer
    --> capnp-0.24.0/src/private/layout.rs:4170:14
     |
4170 |             ((*b) & (1 << (bindex % BITS_PER_BYTE as u64))) != 0
     |              ^^^^ Undefined Behavior occurred here
     |
     = 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 on thread `kani_test_58_mi`:
     = note: inside `<bool as capnp::private::layout::PrimitiveElement>::get` at capnp-0.24.0/src/private/layout.rs:4170:14: 4170:18
note: inside `test_function58`
    --> tests/test_capnp58.rs:12:13
     |
  12 |     let _ = <bool as capnp::private::layout::PrimitiveElement>::get(&_local3, _local5);

What I’m unsure about & suggestion

Since this code lives under capnp::private, it may rely on internal preconditions (e.g., the list reader being well-formed / non-null) that are guaranteed when called through the public API. If so, this could simply be a misuse of internal interfaces in the PoC and not a practical bug for normal users.

If capnp::private is not intended to be used from downstream crates, one defensive option could be to restrict visibility (e.g., pubpub(crate)), which would also prevent accidental external misuse like this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions