From 264555af3cc2ab2919e49e7dea3f8066b9336020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Mon, 3 Aug 2026 11:56:47 -0700 Subject: [PATCH] rpc: avoid descriptor range counter overflow Descriptor ranges may end at `INT32_MAX`, but the expansion loop counts with `int`. Incrementing after the final index overflows, terminating the node in `-ftrapv` builds and invoking undefined behavior otherwise. Use `int64_t` so the final increment stays representable. --- src/rpc/util.cpp | 2 +- test/functional/rpc_scantxoutset.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index a924a23017e..dd097c09915 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -1362,7 +1362,7 @@ std::vector EvalDescriptorStringOrObject(const UniValue& scanobject, Fl range.second = 0; } std::vector ret; - for (int i = range.first; i <= range.second; ++i) { + for (int64_t i = range.first; i <= range.second; ++i) { for (const auto& desc : descs) { std::vector scripts; if (!desc->Expand(i, provider, scripts, provider)) { diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py index b13a251845e..3d2c72e8847 100755 --- a/test/functional/rpc_scantxoutset.py +++ b/test/functional/rpc_scantxoutset.py @@ -80,7 +80,7 @@ class ScantxoutsetTest(BitcoinTestFramework): assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].scantxoutset, "start", [{"desc": "desc", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]}]) assert_raises_rpc_error(-8, "Range specified as [begin,end] must not have begin after end", self.nodes[0].scantxoutset, "start", [{"desc": "desc", "range": [2, 1]}]) assert_raises_rpc_error(-8, "Range is too large", self.nodes[0].scantxoutset, "start", [{"desc": "desc", "range": [0, 1000001]}]) - range_end = 2**31 - 2 # TODO: The largest accepted endpoint overflows the expansion counter. + range_end = 2**31 - 1 assert_equal(self.nodes[0].scantxoutset("start", [{"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": [range_end, range_end]}])['success'], True) self.log.info("Test extended key derivation.")