Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
reachability.cpp
Go to the documentation of this file.
1// Copyright (c) 2026-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <sync.h>
7#include <util/check.h>
8
9#include <compare>
10#include <cstdint>
11#include <cstdio>
12#include <cstdlib>
13#include <iostream>
14#include <map>
15#include <string>
16#include <string_view>
17
18namespace {
19struct GoalId {
20 std::string_view file_name;
21 std::uint_least32_t line;
22 std::uint_least32_t column;
23
24 auto operator<=>(const GoalId&) const = default;
25};
26
27struct GoalState {
28 std::string message;
29 bool reached{false};
30
31 explicit GoalState(std::string_view message) : message{message} {}
32};
33
34class ReachabilityTracker
35{
36public:
37 ReachabilityTracker()
38 {
39 const char* enforce{std::getenv("FUZZ_ENFORCE_REACHABILITY")};
40 if (!enforce || std::string_view{enforce} == "0") return;
41 if (std::string_view{enforce} == "1") {
42 m_enforce = true;
43 return;
44 }
45 std::fputs("FUZZ_ENFORCE_REACHABILITY must be 0 or 1.\n", stderr);
46 std::abort();
47 }
48
50 {
51 LOCK(m_mutex);
52 bool all_reached{true};
53 for (const auto& [id, goal] : m_goals) {
54 std::cerr << (goal.reached ? "PASS" : "FAIL") << " reachability goal \""
55 << goal.message << "\" at " << id.file_name << ':' << id.line << ':' << id.column << '\n';
56 all_reached &= goal.reached;
57 }
58 if (m_enforce && !all_reached) {
59 std::cerr.flush();
60 std::_Exit(EXIT_FAILURE);
61 }
62 }
63
64 void Register(const ReachabilityGoal& goal) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
65 {
66 const GoalId id{
67 .file_name = goal.location.file_name(),
68 .line = goal.location.line(),
69 .column = goal.location.column(),
70 };
71 LOCK(m_mutex);
72 const bool inserted{m_goals.try_emplace(id, goal.message).second};
74 }
75
76 void Observe(bool reached, const ReachabilityGoal& goal) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
77 {
78 const GoalId id{
79 .file_name = goal.location.file_name(),
80 .line = goal.location.line(),
81 .column = goal.location.column(),
82 };
83 LOCK(m_mutex);
84 const auto it{m_goals.find(id)};
85 Assert(it != m_goals.end());
86 it->second.reached |= reached;
87 }
88
89private:
90 Mutex m_mutex;
91 std::map<GoalId, GoalState> m_goals GUARDED_BY(m_mutex);
92 bool m_enforce{false};
93};
94
95ReachabilityTracker g_reachability_tracker;
96} // namespace
97
102
104{
105 g_reachability_tracker.Observe(reached, goal);
106}
#define Assert(val)
Identity function.
Definition check.h:119
void ObserveReachabilityGoal(bool reached, const ReachabilityGoal &goal)
Record whether a registered goal is satisfied by at least one fuzz input.
void RegisterReachabilityGoal(const ReachabilityGoal &goal)
Register a goal before executing any fuzz inputs.
A reachability condition explicitly registered by a fuzz target.
#define LOCK(cs)
Definition sync.h:268
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define GUARDED_BY(x)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82