From 2ab467a63c69640946fde01da2da24abc828e961 Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Mon, 8 Jun 2026 17:38:21 -0500 Subject: [PATCH] fix: guard deprecated service JSON netInfo access --- src/evo/core_write.cpp | 14 ++++++++++---- test/functional/rpc_deprecated.py | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/evo/core_write.cpp b/src/evo/core_write.cpp index 1ccfc998840b..8f7958f14f32 100644 --- a/src/evo/core_write.cpp +++ b/src/evo/core_write.cpp @@ -73,6 +73,12 @@ const std::map RPCRESULT_MAP{{ RESULT_MAP_ENTRY("votingAddress", RPCResult::Type::STR, "Dash address used for voting"), }}; #undef RESULT_MAP_ENTRY + +template +std::string GetDeprecatedServiceField(const Obj& obj) +{ + return CHECK_NONFATAL(obj.netInfo)->GetPrimary().ToStringAddrPort(); +} } // anonymous namespace RPCResult GetRpcResult(const std::string& key, bool optional, const std::string& override_name) @@ -222,7 +228,7 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const UniValue obj(UniValue::VOBJ); obj.pushKV("version", nVersion); if (IsServiceDeprecatedRPCEnabled()) { - obj.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + obj.pushKV("service", GetDeprecatedServiceField(*this)); } obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); obj.pushKV("registeredHeight", nRegisteredHeight); @@ -309,7 +315,7 @@ UniValue CProRegTx::ToJson() const ret.pushKV("collateralHash", collateralOutpoint.hash.ToString()); ret.pushKV("collateralIndex", collateralOutpoint.n); if (IsServiceDeprecatedRPCEnabled()) { - ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + ret.pushKV("service", GetDeprecatedServiceField(*this)); } ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner))); @@ -402,7 +408,7 @@ UniValue CProUpServTx::ToJson() const ret.pushKV("type", std23::to_underlying(nType)); ret.pushKV("proTxHash", proTxHash.ToString()); if (IsServiceDeprecatedRPCEnabled()) { - ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + ret.pushKV("service", GetDeprecatedServiceField(*this)); } ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) { @@ -540,7 +546,7 @@ UniValue CSimplifiedMNListEntry::ToJson(bool extended) const obj.pushKV("proRegTxHash", proRegTxHash.ToString()); obj.pushKV("confirmedHash", confirmedHash.ToString()); if (IsServiceDeprecatedRPCEnabled()) { - obj.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + obj.pushKV("service", GetDeprecatedServiceField(*this)); } obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); obj.pushKV("pubKeyOperator", pubKeyOperator.ToString()); diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index 0780b8515823..7b5226591c43 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -8,9 +8,9 @@ class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 2 + self.num_nodes = 3 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=permissive_bool"]] + self.extra_args = [[], ["-deprecatedrpc=permissive_bool"], ["-deprecatedrpc=service"]] def run_test(self): # This test should be used to verify correct behaviour of deprecated @@ -25,6 +25,7 @@ def run_test(self): # self.generate(self.nodes[1], 1) # self.log.info("No tested deprecated RPC methods") self.test_permissive_bool() + self.test_malformed_deprecated_service_rawtransactions() def test_permissive_bool(self): self.log.info("Test -deprecatedrpc=permissive_bool") @@ -58,5 +59,16 @@ def test_permissive_bool(self): assert_raises_rpc_error(-8, "detailed must be true, false, yes, no, 1 or 0 (not '2')", self.nodes[1].protx, "list", "valid", 2) assert_raises_rpc_error(-8, "detailed must be true, false, yes, no, 1 or 0 (not 'notabool')", self.nodes[1].protx, "list", "valid", "notabool") + def test_malformed_deprecated_service_rawtransactions(self): + self.log.info("Test malformed provider payloads do not crash -deprecatedrpc=service") + node = self.nodes[2] + block_count = node.getblockcount() + for tx_hex in [ + "03000100000000000000020000", # ProRegTx with only nVersion=0 payload + "03000200000000000000020000", # ProUpServTx with only nVersion=0 payload + ]: + assert_raises_rpc_error(-1, "Internal bug detected: obj.netInfo", node.decoderawtransaction, tx_hex) + assert_equal(node.getblockcount(), block_count) + if __name__ == '__main__': DeprecatedRpcTest().main()