policy: reject invalid CFeeRate values when deserializing #36816

pull ryanofsky wants to merge 1 commits into bitcoin:master from ryanofsky:pr/feerate-unser changing 2 files +36 −1
  1. ryanofsky commented at 4:37 PM on November 9, 2026: contributor

    Problem: With the UnstableChain IPC interface from #29409 merged, an IPC client could make bitcoin-node hit an Assume failure (debug builds) or compute wrong fees (release builds) by passing a malformed feerate to broadcastTransaction, calculateIndividualBumpFees or calculateCombinedBumpFee. These methods take feerates as serialized Data fields, and CFeeRate deserialization reads the fee and size without the checks its constructors do, so it accepts a negative size, which fee calculations require to be positive, and a zero size with a nonzero fee, which compares as an infinite feerate. Nothing deserializes a CFeeRate on master today.

    Solution: Make CFeeRate deserialization throw on values its constructors cannot produce, the same way other malformed serialized data is rejected. The change is a SER_READ check in src/policy/feerate.h plus a unit test. It is similar to #36520, which handles other invalid arguments to Chain IPC methods.

    This issue was found by Project Loupe and passed on by instagibbs.

  2. policy: reject invalid CFeeRate values when deserializing
    CFeeRate constructors turn a non-positive size into the empty feerate
    {0, 0}, but Unserialize read fee and size from the stream unchecked.
    A negative size then reaches FeeFrac::EvaluateFee, which requires a
    positive size: debug builds hit an Assume failure, and release builds
    compute wrong fees. A zero size with a nonzero fee compares as an
    infinite feerate.
    
    Nothing deserializes a CFeeRate on master, but the UnstableChain IPC
    interface in #29409, used by the multiprocess wallet in #10102, passes
    feerates as serialized Data fields, so an IPC client could send these
    values.
    
    Throw on values the constructors cannot produce, like other
    deserialization errors.
    
    This issue was found by Project Loupe and passed on by Greg Sanders.
    
    This change was written with Claude Opus 5.5.
    1c6060e7f6
  3. DrahtBot added the label TX fees and policy on Nov 9, 2026
  4. DrahtBot commented at 4:37 PM on November 9, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process. A summary of reviews will appear here.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  5. maflcko commented at 4:49 PM on November 9, 2026: member

    Can the IPC client not still cause aborts via ftrapv or incorrect results, by just passing a feerate so large that it overflows later calculations?

  6. ryanofsky commented at 5:26 PM on November 9, 2026: contributor

    re: #36816 (comment)

    Can the IPC client not still cause aborts via ftrapv or incorrect results, by just passing a feerate so large that it overflows later calculations?

    This might be possible, and if it is, it seems like the type of fix that would belong in #36520, which adds extra error checking to IPC methods, since it's not specific to the CFeeRate class and could happen with other numeric arguments.

    Or if you're suggesting the problem here does not necessarily need to be solved, and it's ok for debug builds to crash and release builds to produce bad results if they are given bad values, maybe that could make sense too.

    This PR is narrower: it only rejects serialized values that CFeeRate's constructors can't produce, like a negative size, which hits Assume(size > 0) in FeeFrac::EvaluateFee. A feerate that's valid but too large for later calculations is a range problem, the same one RPC methods avoid by bounding feerates in ParseFeeRate, so I'd check it where the IPC method receives the value.

  7. maflcko commented at 8:07 AM on November 10, 2026: member

    Ok, I see. Maybe turn this into a draft for now, given that it modifies dead/unreachable code and depends on #29409, which is not a draft, but again depends on https://github.com/bitcoin-core/libmultiprocess/pull/377?

    Once the code is reachable, a small dummy test of the form #36093 could be added to this pull?


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-11-10 20:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me