Skip to content

DemAwareDecoder silently wraps observable bits past 64 (no width guard) #430

Description

@ciaranra

Bug

DemAwareDecoder accepts a DEM with more than 64 observables and then packs
predictions with a u64 bitmask, so observable indices >= 64 wrap onto low bits.

  • PyDemAwareDecoder::from_dem builds a DemCheckMatrix and never calls
    ensure_observables_fit_u64 — that guard appears zero times in
    python/pecos-rslib/src/decoder_bindings.rs.
  • At decode time it calls the narrow packer
    DemCheckMatrix::observables_mask_from_correction
    (python/pecos-rslib/src/decoder_bindings.rs:2417-2419), which does
    mask |= 1 << i into a u64
    (crates/pecos-decoder-core/src/dem.rs:629-639).
  • For i >= 64 that shift panics in debug builds and is masked (i % 64) in
    release builds, so observable 64 silently sets the bit for observable 0.

The wide-safe sibling already exists immediately below it:
observables_obsmask_from_correction (crates/pecos-decoder-core/src/dem.rs:646-657),
which is what the string-registry wrappers use
(python/pecos-rslib/src/fault_tolerance_bindings.rs:2168).

Other matching decoders reject wide DEMs loudly instead: Tesseract errors at
construction (crates/pecos-tesseract/src/decoder.rs:187-198) and Fusion Blossom
rejects observable index >= 64 at edge insertion
(crates/pecos-fusion-blossom/src/decoder.rs:689-697).

Expected

Either make DemAwareDecoder wide (use observables_obsmask_from_correction
and widen the result getter), or reject >64-observable DEMs at construction with
the same actionable message the other narrow decoders use. Silent bit-wrapping
is the one outcome that must not remain.

Severity

severity:critical per the repository definition: silently wrong results in
release builds, with no error surfaced. Blast radius is limited to DEMs with
more than 64 observables decoded through DemAwareDecoder (the BP+OSD entry
point documented in docs/workflows/guppy-dem-decoding.md).

Provenance

Found by an adversarial design-review panel on
pecos-docs/design/construction-and-decoding-api-shape.md, then verified
directly against the code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrustPull requests that update rust codeseverity:criticalSilently wrong results, data loss, or security exposure

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions