ci: Key rippled UBSan suppressions by source file

The function-name suppressions for rippled's own code never matched: this
UBSan build runs without symbol information, so the runtime only reports
the file:line of each diagnostic, not the enclosing function. The CI log
still showed ~486 unsuppressed `runtime error:` lines, all from own-code
files whose entries were written as function-name globs.

Re-key every rippled own-code entry by source file (the only granularity
the runtime can match here), covering all files flagged by the ubsan job:
amount/number arithmetic, hashing and PRNG, counter/sentinel wraparound
guarded by explicit checks, codec index math, and intentional test
arithmetic. Each entry keeps a comment naming the construct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Pratik Mankawde
2026-06-11 17:03:16 +01:00
parent e6a9cc7255
commit db79925e17

View File

@@ -130,46 +130,32 @@ unsigned-integer-overflow:include/c++/*/bit
# Rippled code suppressions
# =============================================================================
# Signed integer negation (-value) in amount types.
# INT64_MIN cannot occur in practice due to domain invariants (mantissa ranges
# are well within int64_t bounds), but UBSan flags the pattern as potential
# signed overflow. Narrowed to operator- to avoid suppressing unrelated
# overflows anywhere in a stack trace containing these type names.
signed-integer-overflow:operator-*IOUAmount*
signed-integer-overflow:operator-*XRPAmount*
signed-integer-overflow:operator-*MPTAmount*
signed-integer-overflow:operator-*STAmount*
# These suppressions are keyed by SOURCE FILE, not function name. This UBSan
# build runs without symbol information, so the runtime only knows the
# file:line of each report, never the enclosing function — function-name
# patterns silently never match. Each entry below is therefore scoped to the
# file whose arithmetic is intentional; the comment names the specific
# construct.
# STAmount::operator+ signed addition — operands are bounded by total supply
# (~10^17 for XRP, ~10^18 for MPT) so overflow cannot occur in practice.
signed-integer-overflow:operator+*STAmount*
# STAmount amount-type arithmetic. Unary negation of the mantissa in xrp()/
# iou()/mpt()/canonicalize() and getInt64Value, plus bounded +/- on amounts:
# INT64_MIN cannot occur because canonicalize() keeps the mantissa well within
# int64_t, and operands are bounded by total supply (~10^17 XRP, ~10^18 MPT).
signed-integer-overflow:protocol/STAmount.cpp
# STAmount::getRate uses unsigned shift and addition
unsigned-integer-overflow:*STAmount*getRate*
# STAmount::serialize uses unsigned bitwise operations
unsigned-integer-overflow:*STAmount*serialize*
# nft::cipheredTaxon uses intentional uint32 wraparound (LCG permutation);
# the helper lives in the generated protocol header nft.h.
unsigned-integer-overflow:protocol/nft.h
# nft::cipheredTaxon uses intentional uint32 wraparound (LCG permutation)
unsigned-integer-overflow:cipheredTaxon
# STPathElement::getHash multiplies/adds accumulators (non-secure, speed-first).
unsigned-integer-overflow:protocol/STPathSet.cpp
# Signed negation of INT64_MIN in STAmount accessors. xrp()/iou()/mpt() and
# getInt64Value negate the mantissa when isNegative_; the mantissa is bounded
# well within int64_t by canonicalize(), so INT64_MIN cannot occur in practice.
# (The operator-*STAmount* entry above only covers binary/unary operator-.)
signed-integer-overflow:*STAmount*xrp*
signed-integer-overflow:*STAmount*iou*
signed-integer-overflow:*STAmount*mpt*
signed-integer-overflow:*STAmount*canonicalize*
signed-integer-overflow:getInt64Value*
# Hash helpers using intentional unsigned wraparound (non-secure, speed-first).
# STPathElement::getHash multiplies/adds accumulators; XorShiftEngine is a PRNG.
unsigned-integer-overflow:*STPathElement*getHash*
unsigned-integer-overflow:*XorShiftEngine*
# beast XorShiftEngine PRNG and murmurhash3 mixing wrap by design.
unsigned-integer-overflow:beast/xor_shift_engine.h
# Number::normalizeToRange multiplies the mantissa by powers of ten; the result
# is intentionally allowed to wrap while searching for the in-range value.
unsigned-integer-overflow:*Number*normalizeToRange*
unsigned-integer-overflow:basics/Number.h
# Counter / sequence arithmetic with intentional unsigned wraparound, each
# guarded by an explicit overflow or domain check at the call site:
@@ -177,32 +163,34 @@ unsigned-integer-overflow:*Number*normalizeToRange*
# ApplyView::insertPage ++page is asserted to wrap to 0 (page exhaustion);
# confineOwnerCount documents "overflow is well defined on unsigned";
# NFTokenMint checks tokenSeq + 1u == 0u; AmendmentTable does (seq - 1) / 256.
unsigned-integer-overflow:*base_uint*operator++*
unsigned-integer-overflow:*base_uint*operator--*
unsigned-integer-overflow:*insertPage*
unsigned-integer-overflow:confineOwnerCount*
unsigned-integer-overflow:*NFTokenMint*doApply*
unsigned-integer-overflow:*AmendmentTableImpl*needValidatedLedger*
unsigned-integer-overflow:basics/base_uint.h
unsigned-integer-overflow:ledger/ApplyView.cpp
unsigned-integer-overflow:ledger/helpers/AccountRootHelpers.cpp
unsigned-integer-overflow:tx/transactors/nft/NFTokenMint.cpp
unsigned-integer-overflow:app/misc/detail/AmendmentTable.cpp
# Sentinel / bounded subtractions that wrap by design (loop counters, reverse
# iteration, "not found" sentinels, balance math bounded by issuance invariants).
unsigned-integer-overflow:*SHAMap*lowerBound*
unsigned-integer-overflow:*permissionToTxType*
unsigned-integer-overflow:b256ToB58Be*
unsigned-integer-overflow:*base64*decode*
unsigned-integer-overflow:*NetworkOPsImp*apply*
unsigned-integer-overflow:*NetworkOPsImp*getBookPage*
unsigned-integer-overflow:*OracleSet*preclaim*
unsigned-integer-overflow:*availableMPTAmount*
unsigned-integer-overflow:RFC1751*getWordFromBlob*
unsigned-integer-overflow:*StrandFlow*
unsigned-integer-overflow:*ValueProxy*operator+*
# iteration, "not found" sentinels, balance math bounded by issuance invariants,
# base58/base64 codec index math, hash-router and role bit math).
unsigned-integer-overflow:shamap/SHAMap.cpp
unsigned-integer-overflow:protocol/Permissions.cpp
unsigned-integer-overflow:protocol/tokens.cpp
unsigned-integer-overflow:basics/base64.cpp
unsigned-integer-overflow:json/json_value.cpp
unsigned-integer-overflow:app/misc/NetworkOPs.cpp
unsigned-integer-overflow:rpc/detail/Role.cpp
unsigned-integer-overflow:tx/transactors/oracle/OracleSet.cpp
unsigned-integer-overflow:ledger/helpers/MPTokenHelpers.cpp
unsigned-integer-overflow:crypto/RFC1751.cpp
unsigned-integer-overflow:tx/paths/detail/StrandFlow.h
unsigned-integer-overflow:protocol/STObject.h
# GetAggregatePrice negates an unsigned trim count to step a reverse iterator;
# trimCount is bounded by the price set size.
unsigned-integer-overflow:*doGetAggregatePrice*
unsigned-integer-overflow:rpc/handlers/orderbook/GetAggregatePrice.cpp
# Test-only intentional overflow/underflow in fixture and unit-test arithmetic.
unsigned-integer-overflow:tests/libxrpl/basics/RangeSet.cpp
unsigned-integer-overflow:test/app/Batch_test.cpp
unsigned-integer-overflow:test/app/Invariants_test.cpp
unsigned-integer-overflow:test/app/Loan_test.cpp