Skip to content

fix(helpers): prevent u8 overflow in signer fee multiplier - #340

Open
e-desouza wants to merge 1 commit into
mainfrom
fix/issue-238-fee-overflow
Open

fix(helpers): prevent u8 overflow in signer fee multiplier#340
e-desouza wants to merge 1 commit into
mainfrom
fix/issue-238-fee-overflow

Conversation

@e-desouza

Copy link
Copy Markdown
Collaborator

Why

calculate_fee_per_transaction_type computed (1 + signers_count) where signers_count: u8. At the maximum value of 255, this performs u8 addition: debug builds panic; release builds wrap silently to 0, zeroing the signer fee surcharge and producing a transaction with an incorrect fee.

is_not_later_rippled_version split the server's build_version string and accessed the resulting Vec at indices 1 and 2 without a length check. A non-semver build_version string (e.g. a dev build returning "1") panicked every autofill call.

calculate_based_on_fulfillment collected chars().map(|c| c as u8) to compute a byte length for the EscrowFinish fee formula. This silently undercounts for multi-byte codepoints and allocates unnecessarily.

Fixes #238.

What changed

  • Line 178 of asynch/transaction/mod.rs: widened to 1u64 + signers_count as u64.
  • is_not_later_rippled_version: added if source_decomp.len() < 3 || target_decomp.len() < 3 { return Ok(false); } before any index access.
  • calculate_based_on_fulfillment: replaced chars().map(|c| c as u8).collect::<Vec<_>>().len() with fulfillment.len().

How to validate

cargo test --release

Regression test test_fee_signer_multiplier_overflow_guard verifies the production expression yields BigDecimal::from(256) for signers_count = 255.

The expression `(1 + signers_count)` performed u8 arithmetic where
`signers_count: u8`. At the protocol maximum of 255 signers this wraps
to 0 in release builds (silent wrong fee) and panics in debug builds.
Widened both operands to u64 before adding.

XRPL protocol caps SignerList entries well below 255 in practice, so
this is a robustness/debug-panic fix, not a reachable issue.

Adds `test_fee_calculation_signers_count_max` as a regression guard.
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.71%. Comparing base (c83df4f) to head (960bda8).

Files with missing lines Patch % Lines
src/asynch/transaction/mod.rs 50.00% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #340   +/-   ##
=======================================
  Coverage   86.71%   86.71%           
=======================================
  Files         252      252           
  Lines       32630    32632    +2     
=======================================
+ Hits        28296    28298    +2     
  Misses       4334     4334           
Flag Coverage Δ
integration 71.36% <50.00%> (+0.03%) ⬆️
unit 87.33% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/asynch/transaction/mod.rs 70.08% <50.00%> (+0.24%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens fee calculation and version parsing in the async transaction helper layer to prevent panics and incorrect fee computation under edge-case inputs.

Changes:

  • Prevents u8 overflow in the signer fee multiplier by widening arithmetic before converting to BigDecimal.
  • Avoids panics in is_not_later_rippled_version by adding a length check before indexing version components.
  • Improves EscrowFinish fulfillment fee computation by using the string’s byte length directly (removing an unnecessary allocation), and adds a regression test for the signer multiplier overflow case.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +549 to +553
// Regression guard for issue #238: (1 + signers_count) as u8 overflows at 255
// in release builds, or panics in debug builds. The fix widens to u64 first.
// NOTE: A full behavioral test of calculate_fee_per_transaction_type requires a
// mock AsyncClient — this test guards the arithmetic expression at line 178.
#[test]
Comment on lines +556 to +558
// Production expression from calculate_fee_per_transaction_type line 178:
// let signer_count_fee_decimal: BigDecimal = (1u64 + signers_count as u64).into();
let multiplier: BigDecimal = (1u64 + signers_count as u64).into();
@e-desouza
e-desouza force-pushed the fix/issue-238-fee-overflow branch 2 times, most recently from 62a7ee7 to 960bda8 Compare July 15, 2026 18:37
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.

Fee multiplier overflow: (1 + signers_count): u8

2 participants