fuzz: connman: add AddNode/RemoveAddedNode invariants
What changed, and why it matters
This commit only changes a fuzz test file. Fuzz tests are automated tools that throw random inputs at code to find bugs. It adds checks that verify how Bitcoin Core's connection manager handles manually added nodes. There is no change to production code, no fix for a real vulnerability, and no security risk to users.
No action needed. This is a test-only improvement and does not affect running Bitcoin Core nodes.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit modifies src/test/fuzz/connman.cpp, a fuzzing harness for CConnman. It adds invariants around AddNode and RemoveAddedNode: after a successful AddNode, a duplicate AddNode must fail and GetAddedNodeInfo must grow; after RemoveAddedNode, the list must shrink back. It also moves RemoveAddedNode into its own fuzz action and restricts a final GetAddedNodeInfo call to non-connected nodes. These are test-only assertions to improve coverage and catch regressions in the connection manager’s added-node state machine.
Changed components
src/test/fuzz/connman.cppInspect captured patch +20 / −5
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index ff7f4ad7..214ba14f 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -107,6 +107,7 @@ FUZZ_TARGET(connman, .init = initialize_connman)
CSubNet random_subnet;
std::string random_string;
std::vector<NodeId> node_ids;
+ std::vector<std::string> node_addr_names;
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
CNode& p2p_node{*ConsumeNodeAsUniquePtr(fuzzed_data_provider).release()};
@@ -114,6 +115,7 @@ FUZZ_TARGET(connman, .init = initialize_connman)
p2p_node.fSuccessfullyConnected = true;
connman.AddTestNode(p2p_node);
node_ids.push_back(p2p_node.GetId());
+ node_addr_names.push_back(p2p_node.m_addr_name);
}
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
@@ -132,7 +134,23 @@ FUZZ_TARGET(connman, .init = initialize_connman)
random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
},
[&] {
- connman.AddNode({random_string, fuzzed_data_provider.ConsumeBool()});
+ const std::string& node_str = (!node_addr_names.empty() && fuzzed_data_provider.ConsumeBool())
+ ? PickValue(fuzzed_data_provider, node_addr_names)
+ : random_string;
+ const auto added_node_info{connman.GetAddedNodeInfo(/*include_connected=*/true)};
+ const auto add_node{connman.AddNode({node_str, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()})};
+ if (add_node) {
+ assert(!connman.AddNode({node_str, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()}));
+ assert(added_node_info.size() < connman.GetAddedNodeInfo(/*include_connected=*/true).size());
+ const auto remove{fuzzed_data_provider.ConsumeBool()};
+ if (remove) {
+ assert(connman.RemoveAddedNode(node_str));
+ assert(added_node_info.size() == connman.GetAddedNodeInfo(/*include_connected=*/true).size());
+ }
+ }
+ },
+ [&] {
+ (void)connman.RemoveAddedNode(random_string);
},
[&] {
connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
@@ -186,9 +204,6 @@ FUZZ_TARGET(connman, .init = initialize_connman)
serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
connman.PushMessage(&random_node, std::move(serialized_net_msg));
},
- [&] {
- connman.RemoveAddedNode(random_string);
- },
[&] {
const auto set_active{fuzzed_data_provider.ConsumeBool()};
connman.SetNetworkActive(set_active);
@@ -250,7 +265,7 @@ FUZZ_TARGET(connman, .init = initialize_connman)
(void)pnode->IsFullOutboundConn();
(void)pnode->ConnectionTypeAsString();
});
- (void)connman.GetAddedNodeInfo(fuzzed_data_provider.ConsumeBool());
+ (void)connman.GetAddedNodeInfo(/*include_connected=*/false);
(void)connman.GetExtraFullOutboundCount();
assert(connman.GetLocalServices() == local_services);
assert(connman.GetMaxOutboundTarget() == max_outbound_limit);
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.