mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-20 04:03:57 +00:00
Optimize fuzzer (#336)
This commit is contained in:
52
src/common/utils/string.cpp
Normal file
52
src/common/utils/string.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "string.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace utils::string
|
||||
{
|
||||
// NOLINTNEXTLINE(cert-dcl50-cpp)
|
||||
const char* va(const char* format, ...)
|
||||
{
|
||||
constexpr auto buffer_count = 4;
|
||||
thread_local std::array<std::vector<char>, buffer_count> buffers{};
|
||||
thread_local size_t current_index{0};
|
||||
|
||||
const auto index = current_index++;
|
||||
current_index %= buffers.size();
|
||||
|
||||
auto& buffer = buffers.at(index);
|
||||
|
||||
if (buffer.size() < 10)
|
||||
{
|
||||
buffer.resize(10);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
va_list ap{};
|
||||
va_start(ap, format);
|
||||
|
||||
#ifdef _WIN32
|
||||
const int res = vsnprintf_s(buffer.data(), buffer.size(), _TRUNCATE, format, ap);
|
||||
#else
|
||||
const int res = vsnprintf(buffer.data(), buffer.size(), format, ap);
|
||||
#endif
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if (res > 0 && static_cast<size_t>(res) < buffer.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (res == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buffer.resize(std::max(buffer.size() * 2, static_cast<size_t>(1)));
|
||||
}
|
||||
|
||||
return buffer.data();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cwctype>
|
||||
#include <algorithm>
|
||||
@@ -8,6 +9,12 @@
|
||||
|
||||
namespace utils::string
|
||||
{
|
||||
#ifdef __clang__
|
||||
__attribute__((__format__(__printf__, 1, 2)))
|
||||
#endif
|
||||
const char*
|
||||
va(const char* format, ...);
|
||||
|
||||
template <typename T, size_t Size>
|
||||
requires(std::is_trivially_copyable_v<T>)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
|
||||
@@ -14,10 +14,14 @@ namespace utils
|
||||
}
|
||||
|
||||
bool has_elapsed(typename Clock::duration duration) const
|
||||
{
|
||||
return this->elapsed() > duration;
|
||||
}
|
||||
|
||||
typename Clock::duration elapsed() const
|
||||
{
|
||||
const auto now = Clock::now();
|
||||
const auto diff = now - this->point_;
|
||||
return diff > duration;
|
||||
return now - this->point_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
#include "input_generator.hpp"
|
||||
|
||||
#include <utils/timer.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/finally.hpp>
|
||||
|
||||
namespace fuzzer
|
||||
{
|
||||
namespace
|
||||
@@ -45,6 +49,57 @@ namespace fuzzer
|
||||
std::atomic_bool stop_{false};
|
||||
};
|
||||
|
||||
std::string format_binary_data(const std::span<const uint8_t> input)
|
||||
{
|
||||
std::string data;
|
||||
std::string bytes;
|
||||
std::string text;
|
||||
|
||||
const auto wrap_line = [&] {
|
||||
if (bytes.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (bytes.size() < 16 * 3)
|
||||
{
|
||||
bytes.push_back(' ');
|
||||
}
|
||||
|
||||
data += bytes;
|
||||
data += "| ";
|
||||
data += text;
|
||||
data += "\n";
|
||||
|
||||
bytes.clear();
|
||||
text.clear();
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < input.size(); ++i)
|
||||
{
|
||||
if (i % 16 == 0)
|
||||
{
|
||||
wrap_line();
|
||||
}
|
||||
|
||||
const auto in = input[i];
|
||||
bytes += utils::string::va("%02X ", static_cast<uint32_t>(in));
|
||||
text.push_back(isprint(in) ? static_cast<char>(in) : '.');
|
||||
}
|
||||
|
||||
wrap_line();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void print_crash(const std::span<const uint8_t> input)
|
||||
{
|
||||
std::string text = utils::string::va("\nFound crash for input (length %zu):\n", input.size());
|
||||
text += format_binary_data(input);
|
||||
|
||||
printf("%.*s\n", static_cast<int>(text.size()), text.c_str());
|
||||
}
|
||||
|
||||
void perform_fuzzing_iteration(fuzzing_context& context, executer& executer)
|
||||
{
|
||||
++context.executions;
|
||||
@@ -56,8 +111,7 @@ namespace fuzzer
|
||||
|
||||
if (result == execution_result::error)
|
||||
{
|
||||
printf("Found error!\n");
|
||||
context.stop();
|
||||
print_crash(input);
|
||||
}
|
||||
|
||||
return score;
|
||||
@@ -111,6 +165,7 @@ namespace fuzzer
|
||||
|
||||
void run(fuzzing_handler& handler, const size_t concurrency)
|
||||
{
|
||||
const utils::timer<> t{};
|
||||
input_generator generator{};
|
||||
fuzzing_context context{generator, handler};
|
||||
worker_pool pool{context, concurrency};
|
||||
@@ -125,5 +180,9 @@ namespace fuzzer
|
||||
printf("Executions/s: %" PRIu64 " - Score: %" PRIx64 " - Avg: %.3f\n", executions, highest_scorer.score,
|
||||
avg_score);
|
||||
}
|
||||
|
||||
const auto duration = t.elapsed();
|
||||
const int64_t seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
|
||||
printf("Fuzzing stopped after %" PRIi64 "s\n", seconds);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user