Skip to content

Rational has no checked-arithmetic mode; intermediate cross-terms can overflow before final results do #130

Description

@Yaraslaut

Summary

morph::math::Rational has no checked-arithmetic mode. operator+/operator- on plain Rational pairs are fixed-width std::int64_t arithmetic, not saturating and not exception-throwing by signature — at ledger-realistic magnitudes, summing enough rows genuinely triggers real signed-integer overflow (undefined behavior), with no way for a calling application to detect this before committing corrupted state.

Evidence

A binary-search fuzz test (tests/test_ledger_rational_fuzz.cpp, added while implementing rung 5 / ledger) measures the exact boundary empirically, via real Rational::operator+ calls (not a hand-computed estimate): summing dp=2 legs at 10^9 minor units each, the boundary is exactly 9,223,372,037 rows (INT64_MAX / 10^9 + 1).

This isn't a hypothetical: while adding this very fuzz test, an early implementation attempt hit real signed-overflow UB directly (an exponentiation-by-squaring helper doubling one step past what it needed), independently confirmed by two rounds of scoped review before landing a provably-safe version. Rational's own arithmetic operators offer no built-in guard against the same class of bug in application code that doesn't happen to structure its summation as carefully.

Suggested direction

A checked-arithmetic mode — an expected<Rational, Overflow>-returning operator+/operator- alongside the existing noexcept ones, or at minimum a debug-mode overflow assertion — would let a ledger-scale (or otherwise large-magnitude) application detect this before committing corrupted state, rather than relying on the app never summing enough rows to hit the boundary in practice.

Reference

Filed from LASTRADA-Software/morph, branch ladder-ledger-rung5 (not yet merged), as docs/findings/001-rational-checked-arithmetic-mode.md (see that file for the same summary in the ladder's own findings-pipeline format, examples/FINDINGS.md) and tests/test_ledger_rational_fuzz.cpp for the reproducing test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions