Skip to content

chore: replace the unsound static-mut and ignored-Result patterns - #604

Open
blacks1ne wants to merge 1 commit into
QuilibriumNetwork:v2.1.0.25from
blacks1ne:chore/warnings-soundness
Open

chore: replace the unsound static-mut and ignored-Result patterns#604
blacks1ne wants to merge 1 commit into
QuilibriumNetwork:v2.1.0.25from
blacks1ne:chore/warnings-soundness

Conversation

@blacks1ne

@blacks1ne blacks1ne commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

10 warnings, fixed rather than silenced. This is the only PR in the series
besides #597 that changes runtime behaviour, so it is worth a closer read than
the rest.

static_mut_refs (5). bls::singleton's SINGLETON and bls256's G2_TAB
both used static mut + Once + assume_init, which needs unsafe at every
access and has no synchronisation on the read side. Both become OnceLock.
get_or_init returns &'static T, so singleton() keeps its exact signature
and loses its unsafe block entirely. bls256::init() is called from exactly
one place — inside singleton()'s initialiser — so the ordering is unchanged; a
missing init() now panics loudly instead of silently pairing against an
all-zero table. (static_mut_refs becomes a hard error in edition 2024, so this
has to happen eventually either way.)

unused_must_use (2). doubleratchet::ratchet_ephemeral_keys discarded both
hkdf.expand results. They cannot fail here — 96 bytes is well under SHA-512's
16320-byte limit — but if they ever did, the ratchet would have continued with a
zeroed key buffer. The function already returns Result, so they are propagated
with the bound spelled out in a comment.

unused_assignments (3). Including clock.rs's have_frame, which is now
an uninitialised binding so the compiler enforces that every path sets it. That
flag guards the latest-index pointer against an attacker-chosen frame_number,
so a future path that forgets to set it should not silently inherit false.

The full test suite passes on this — see the verification below — which is the
main evidence that the OnceLock ordering is right.


Series

Part of the warning-cleanup series that starts with #597. The eight PRs are
disjoint and each stands on its own, but they are meant to be read in order —
please take #597 first: it is the only one of the eight that fixes a bug
rather than a warning, and it is the shortest.

Ten soundness warnings, each fixed rather than silenced.

static_mut_refs (5). Two lazily-initialised process globals used the
'static mut + Once + assume_init' pattern, which needs unsafe at every access
and has no synchronisation on the read side:

  - bls::singleton()'s SINGLETON becomes a OnceLock<SingletonKZGSetup>.
    get_or_init returns &'static T directly, so the function keeps its exact
    signature and loses its unsafe block entirely.
  - bls256's G2_TAB becomes a OnceLock<[FP16; G2_TABLE]>. init() fills a local
    and publishes it; the two verification paths take it via
    .expect("bls256::init() must run before verification"). Previously a
    missing init() meant silently pairing against an all-zero table; now it is
    a loud panic. init() is called from exactly one place (inside
    singleton()'s initialiser), so the ordering is unchanged.

unused_must_use (2). doubleratchet::ratchet_ephemeral_keys ignored both
hkdf.expand results. They cannot actually fail here — expand only errors when
the output exceeds 255*HashLen, and 96 is a constant well under SHA-512's
16320 — but the ratchet silently continued with a zeroed key buffer if it
ever did. The enclosing function already returns Result, so the error is
propagated with a note explaining why it is unreachable.

unused_assignments (3).
  - lattice_ct::decode_pending_claim initialised 'p' to 0 and immediately
    overwrote it with 32; it now starts at 32.
  - clock::commit_shard_clock_frame's have_frame was initialised to false and
    assigned on both branches; it is now a plain uninitialised binding, so the
    compiler enforces that every path sets it. That flag guards the
    latest-index pointer against an attacker-chosen frame_number, so a future
    path that forgets to set it should not silently inherit 'false'.
  - addressing::location_clone_is_independent mutated 'a' and never checked
    it. The test now asserts on both halves, which is what it was for.

(cherry picked from commit f5522adcb2fbf1da39a0833ddd1daacfbe6e2d79)
@blacks1ne
blacks1ne force-pushed the chore/warnings-soundness branch from 20a82b5 to 85c74fa Compare August 18, 2026 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant