bb_fuzzer.cpp
Go to the documentation of this file.
2 #include <fuzzer/FuzzedDataProvider.h>
3 #include <iostream>
4 #include <vector>
5 #include <memory>
6 #include <thread>
7 
8 #include <iomanip>
9 
11 {
12 public:
13  static bool isExpectedException(const std::exception& e)
14  {
15  const std::string what = e.what();
16  const std::vector<std::string> expected_patterns = { "Blackboard::set",
17  "once declared, the type of a "
18  "port shall not change",
19  "Missing key",
20  "hasn't been initialized",
21  "Missing parent blackboard",
22  "Floating point truncated",
23  "Value outside the max "
24  "numerical limit",
25  "Value outside the lovest "
26  "numerical limit",
27  "Value is negative and can't be "
28  "converted to unsigned",
29  "Implicit casting to bool is "
30  "not allowed" };
31 
32  for(const auto& pattern : expected_patterns)
33  {
34  if(what.find(pattern) != std::string::npos)
35  {
36  return true;
37  }
38  }
39  return false;
40  }
41 };
42 
44 {
45 private:
46  std::vector<BT::Blackboard::Ptr> blackboards_;
47  std::vector<std::string> generated_keys_;
48  FuzzedDataProvider& fuzz_data_;
49 
50  std::string generateKey()
51  {
52  const std::string key_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01"
53  "23456789_@";
54  size_t length = fuzz_data_.ConsumeIntegralInRange<size_t>(1, 32);
55  std::string key;
56  for(size_t i = 0; i < length; ++i)
57  {
58  key +=
59  key_chars[fuzz_data_.ConsumeIntegralInRange<size_t>(0, key_chars.length() - 1)];
60  }
61  generated_keys_.push_back(key);
62  return key;
63  }
64 
66  {
67  if(!bb)
68  return;
69 
70  try
71  {
72  // Create random entry
73  std::string key = generateKey();
74  switch(fuzz_data_.ConsumeIntegralInRange<size_t>(0, 6))
75  {
76  case 0:
77  bb->set(key, fuzz_data_.ConsumeIntegral<int>());
78  break;
79  case 1:
80  bb->set(key, fuzz_data_.ConsumeFloatingPoint<double>());
81  break;
82  case 2:
83  bb->set(key, fuzz_data_.ConsumeRandomLengthString());
84  break;
85  case 3:
86  bb->set(key, fuzz_data_.ConsumeBool());
87  break;
88  case 4:
89  bb->set(key, fuzz_data_.ConsumeIntegral<uint64_t>());
90  break;
91  case 5:
92  bb->set(key, fuzz_data_.ConsumeFloatingPoint<float>());
93  break;
94  case 6: {
95  // Try to get non-existent key
96  bb->get<int>(generateKey());
97  break;
98  }
99  }
100 
101  // Random operations on existing keys
102  if(!generated_keys_.empty())
103  {
104  const auto& existing_key =
105  generated_keys_[fuzz_data_.ConsumeIntegralInRange<size_t>(
106  0, generated_keys_.size() - 1)];
107 
108  switch(fuzz_data_.ConsumeIntegralInRange<size_t>(0, 4))
109  {
110  case 0:
111  bb->unset(existing_key);
112  break;
113  case 1:
114  bb->getEntry(existing_key);
115  break;
116  case 2:
117  bb->get<int>(existing_key);
118  break;
119  case 3:
120  bb->get<double>(existing_key);
121  break;
122  case 4:
123  bb->get<std::string>(existing_key);
124  break;
125  }
126  }
127 
128  // Random remapping operations
129  if(generated_keys_.size() >= 2)
130  {
131  size_t idx1 =
132  fuzz_data_.ConsumeIntegralInRange<size_t>(0, generated_keys_.size() - 1);
133  size_t idx2 =
134  fuzz_data_.ConsumeIntegralInRange<size_t>(0, generated_keys_.size() - 1);
135  bb->addSubtreeRemapping(generated_keys_[idx1], generated_keys_[idx2]);
136  }
137  }
138  catch(const std::exception& e)
139  {
141  {
142  throw;
143  }
144  }
145  }
146 
148  {
149  if(blackboards_.empty())
150  return;
151 
152  auto parent = blackboards_[fuzz_data_.ConsumeIntegralInRange<size_t>(
153  0, blackboards_.size() - 1)];
154 
155  auto child = BT::Blackboard::create(parent);
156  if(fuzz_data_.ConsumeBool())
157  {
158  child->enableAutoRemapping(true);
159  }
160 
161  blackboards_.push_back(child);
162  }
163 
165  {
166  try
167  {
168  auto json = BT::ExportBlackboardToJSON(*bb);
169  if(fuzz_data_.ConsumeBool())
170  {
171  std::string json_str = json.dump();
172  size_t pos = fuzz_data_.ConsumeIntegralInRange<size_t>(0, json_str.length());
173  json_str.insert(pos, fuzz_data_.ConsumeRandomLengthString());
174  json = nlohmann::json::parse(json_str);
175  }
177  }
178  catch(const std::exception& e)
179  {
181  {
182  throw;
183  }
184  }
185  }
186 
187 public:
188  explicit BlackboardFuzzer(FuzzedDataProvider& provider) : fuzz_data_(provider)
189  {
191  }
192 
193  void fuzz()
194  {
195  size_t num_operations = fuzz_data_.ConsumeIntegralInRange<size_t>(50, 200);
196 
197  for(size_t i = 0; i < num_operations && !blackboards_.empty(); ++i)
198  {
199  try
200  {
201  // Randomly select a blackboard to operate on
202  size_t bb_idx =
203  fuzz_data_.ConsumeIntegralInRange<size_t>(0, blackboards_.size() - 1);
204  auto bb = blackboards_[bb_idx];
205 
206  switch(fuzz_data_.ConsumeIntegralInRange<size_t>(0, 3))
207  {
208  case 0:
209  // Fuzz single blackboard operations
210  fuzzSingleBB(bb);
211  break;
212 
213  case 1:
214  // Create new blackboards in hierarchy
215  if(fuzz_data_.ConsumeBool())
216  {
218  }
219  break;
220 
221  case 2:
222  // JSON operations
223  fuzzJsonOperations(bb);
224  break;
225 
226  case 3:
227  // Cleanup operations
228  if(fuzz_data_.ConsumeBool() && blackboards_.size() > 1)
229  {
230  size_t remove_idx =
231  fuzz_data_.ConsumeIntegralInRange<size_t>(0, blackboards_.size() - 1);
232  blackboards_.erase(blackboards_.begin() + remove_idx);
233  }
234  break;
235  }
236  }
237  catch(const std::exception& e)
238  {
240  {
241  std::cerr << "Unexpected exception: " << e.what() << std::endl;
242  throw;
243  }
244  }
245  }
246  }
247 };
248 
249 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
250 {
251  if(size < 64)
252  return 0;
253 
254  try
255  {
256  FuzzedDataProvider fuzz_data(data, size);
257  BlackboardFuzzer fuzzer(fuzz_data);
258  fuzzer.fuzz();
259  }
260  catch(const std::exception& e)
261  {
263  {
264  std::cerr << "Unexpected top-level exception: " << e.what() << std::endl;
265  return 1;
266  }
267  }
268 
269  return 0;
270 }
cx::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: wildcards.hpp:636
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: bb_fuzzer.cpp:249
BlackboardFuzzer::BlackboardFuzzer
BlackboardFuzzer(FuzzedDataProvider &provider)
Definition: bb_fuzzer.cpp:188
BlackboardFuzzer::generateKey
std::string generateKey()
Definition: bb_fuzzer.cpp:50
BT::ImportBlackboardFromJSON
void ImportBlackboardFromJSON(const nlohmann::json &json, Blackboard &blackboard)
ImportBlackboardFromJSON will append elements to the blackboard, using the values parsed from the JSO...
Definition: blackboard.cpp:284
ExceptionFilter::isExpectedException
static bool isExpectedException(const std::exception &e)
Definition: bb_fuzzer.cpp:13
basic_json
namespace for Niels Lohmann
Definition: json.hpp:3411
BlackboardFuzzer::blackboards_
std::vector< BT::Blackboard::Ptr > blackboards_
Definition: bb_fuzzer.cpp:46
BT::ExportBlackboardToJSON
nlohmann::json ExportBlackboardToJSON(const Blackboard &blackboard)
ExportBlackboardToJSON will create a JSON that contains the current values of the blackboard....
Definition: blackboard.cpp:267
BlackboardFuzzer::fuzz
void fuzz()
Definition: bb_fuzzer.cpp:193
BlackboardFuzzer::fuzzJsonOperations
void fuzzJsonOperations(BT::Blackboard::Ptr bb)
Definition: bb_fuzzer.cpp:164
BT::Blackboard::Ptr
std::shared_ptr< Blackboard > Ptr
Definition: blackboard.h:35
lexy::parse
constexpr auto parse(const Input &input, const ErrorCallback &callback)
Parses the production into a value, invoking the callback on error.
Definition: parse.hpp:171
BlackboardFuzzer
Definition: bb_fuzzer.cpp:43
lexy_ext::child
auto child(const lexy::parse_tree< Reader, TokenKind, MemoryResource > &tree, typename lexy::parse_tree< Reader, TokenKind, MemoryResource >::node node, Predicate predicate) -> std::optional< typename lexy::parse_tree< Reader, TokenKind, MemoryResource >::node >
Returns the first child that matches predicate, if there is any.
Definition: parse_tree_algorithm.hpp:244
BlackboardFuzzer::fuzz_data_
FuzzedDataProvider & fuzz_data_
Definition: bb_fuzzer.cpp:48
ExceptionFilter
Definition: bb_fuzzer.cpp:10
BlackboardFuzzer::createBlackboardHierarchy
void createBlackboardHierarchy()
Definition: bb_fuzzer.cpp:147
BT::Blackboard::create
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:63
BlackboardFuzzer::generated_keys_
std::vector< std::string > generated_keys_
Definition: bb_fuzzer.cpp:47
basic_json::dump
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition: json.hpp:20574
BlackboardFuzzer::fuzzSingleBB
void fuzzSingleBB(BT::Blackboard::Ptr bb)
Definition: bb_fuzzer.cpp:65
blackboard.h


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Wed Apr 16 2025 02:20:55