bucket-A4: cap Packet read-constructor prefix_length (SAFE-ADDITIVE, Bug-9 hardening)#50
Conversation
…Bug-9 hardening)
Adds a bounds guard to Packet(size_t prefix_length): caps prefix_length at 16
and throws std::ios_base::failure if exceeded, instead of letting
prefix.resize() throw std::length_error ("vector::_M_default_append") and kill
the process.
prefix_length flows from m_node->get_prefix().size() in Socket::init(). In the
Bug-3 UAF class (rapid disconnect-reconnect destroys m_node mid-handshake), the
vector's size field reads garbage and the unguarded resize() aborts. All known
protocols use a 4-byte magic prefix, so the cap at 16 never triggers in normal
operation — this only converts a UAF-garbage crash into a clean connection
failure. LTC+DOGE behavior on valid traffic is identical.
Cherry-picked from dash-spv-embedded HEAD 8249dc2.
1 file, +11:
- modified src/core/packet.hpp
Review — bucket-A4 (#50): Packet prefix_length cap, Bug-9 hardeningVerdict: APPROVE. SAFE-ADDITIVE label verified. All bound-relevant points check out; one non-blocking gap (no unit test for the cap). Bound-by-bound notes below. 1. Cap value / correctness
2. Off-by-one / overflowOperator is 3. Error pathThrows 4. Fuzz / DoS — KEY CLARIFICATION
5. Include hygiene (minor)
6. Test coverage — the one real gap (non-blocking)No unit test exercises the cap. No test file references Packet/prefix, and the PR touches only CIAll green: Linux x86_64 ctest, Windows, macOS arm64, CodeQL, plus btc/ltc/doge/dash smokes. Embedded-smoke skip-fast as expected for this branch. Approvable as-is. Recommend the cap-boundary unit test (point 6) as a fast follow. — ltc-doge-production-steward |
A raw Infinity in the legacy flat-map shape (value is a bare number) was assigned to amount without finite filtering. Infinity > 0 is true, so the row survived and poisoned totalPrimary, producing a non-finite snapshot total. Route the value through num(), which clamps non-finite values to 0 so the existing !(amount > 0) guard discards the row. Surfaced by the fast-check property parseSnapshot: output always has required keys with correct types (seed -1679627146, counterexample [Infinity]) flaking the Web-static verify gate on PRs #49/#50.
Summary
Adds a bounds guard to
Packet(size_t prefix_length): capsprefix_lengthat 16 and throwsstd::ios_base::failureif exceeded, instead of lettingprefix.resize()throwstd::length_error(vector::_M_default_append) and abort the process. Additive hardening — no change to valid-traffic behavior (audit classification: SAFE-ADDITIVE).1 file, +11:
src/core/packet.hppCherry-picked from
dash-spv-embeddedHEAD8249dc28.Context
Part 4 of the bucket-A sub-PRs for the multi-coin landing strategy. Follows #46 (A1), #48 (A2), #49 (A3). Independent of A1–A3 (different file, no shared symbols).
Why this is safe for LTC+DOGE
prefix_lengthflows fromm_node->get_prefix().size()inSocket::init(). All known protocols use a 4-byte magic prefix, so the cap at 16 is never reached in normal operation — theresize(prefix_length)path is unchanged for every valid connection.m_nodemid-handshake → the vector's size field reads garbage → unguardedresize()aborts). It converts that crash into a clean per-connection failure (std::ios_base::failure, already the connection-teardown exception type).CI expectation
linux:+ cross-platform + CodeQL: green.Reviewer
Agent-side reviewer: ltc-doge-production-steward (watches the branch). Integrator (cc) routes human review.
Test plan
linux:CI green (full test suite — exercises the Packet read path on valid LTC/DOGE traffic)src/core/packet.hpptouched (directory-contract spot-check)