From db79925e1779c53cee2896837ae060a924cb285b Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Thu, 11 Jun 2026 17:03:16 +0100 Subject: [PATCH] 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 --- sanitizers/suppressions/ubsan.supp | 92 +++++++++++++----------------- 1 file changed, 40 insertions(+), 52 deletions(-) diff --git a/sanitizers/suppressions/ubsan.supp b/sanitizers/suppressions/ubsan.supp index 9f145db940..7e3e02f855 100644 --- a/sanitizers/suppressions/ubsan.supp +++ b/sanitizers/suppressions/ubsan.supp @@ -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