Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/fuzzing/include/fuzzing/fuzzer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ struct fuzzer final
branching_node* get_best(std::unordered_map<branching_node*, bool>& targets, natural_32_bit max_input_width);

std::unordered_set<branching_node*> loop_heads; // Priority #1 (the highest)
// bool means whether the loop heads were collected
std::unordered_map<branching_node*, bool> sensitive; // Priority #2
std::unordered_map<branching_node*, bool> untouched; // Priority #3
std::unordered_map<location_id, std::pair<branching_node*, bool> > iid_twins; // Priority #4
Expand Down Expand Up @@ -197,7 +198,7 @@ struct fuzzer final
{
branching_node* entry;
branching_node* exit;
branching_node* successor;
// branching_node* successor;
};

struct iid_pivot_props
Expand Down Expand Up @@ -310,7 +311,7 @@ struct fuzzer final
primary_coverage_target_branchings primary_coverage_targets;
std::unordered_map<location_id, iid_location_props> iid_pivots;

std::unordered_set<branching_node*> coverage_failures_with_hope;
std::unordered_set<branching_node*> coverage_failures_with_hope; // EXPLAIN

STATE state;
sensitivity_analysis sensitivity;
Expand Down
65 changes: 59 additions & 6 deletions src/fuzzing/include/fuzzing/progress_recorder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
# include <filesystem>
# include <memory>
# include <iosfwd>
# include <vector>
# include <tuple>

namespace fuzzing {

Expand Down Expand Up @@ -71,15 +73,50 @@ struct progress_recorder
void on_trace_mapped_to_tree(branching_node* leaf_);
void on_execution_results_available();

void on_strategy_turn_primary_loop_head();
void on_strategy_turn_primary_sensitive();
void on_strategy_turn_primary_untouched();
void on_strategy_turn_primary_iid_twins();
void on_strategy_turn_monte_carlo();
void on_strategy_turn_monte_carlo_backward();
void on_strategy_turn_primary_loop_head(branching_node* const node);
void on_strategy_turn_primary_sensitive(branching_node* const node);
void on_strategy_turn_primary_untouched(branching_node* const node);
void on_strategy_turn_primary_iid_twins(branching_node* const node);
void on_strategy_turn_monte_carlo(branching_node* const node);
void on_strategy_turn_monte_carlo_backward(branching_node* const node);
void on_post_node_closed(branching_node* node);
void flush_post_data();

enum SELECTION_REASON
{
UNKNOWN = 0,

SENSITIVITY_PRIORITY_START = 1,
UNTOUCHED_PRIORITY_START = 2,

PRIORITY_STEP_NO_SENSITIVITY_PERFORMED = 3,
PRIORITY_STEP_SENSITIVITY_BITS_SIZE = 4,
PRIORITY_STEP_DISTANCE_TO_WIDTH = 5,
PRIORITY_STEP_STDIN_SIZE = 6,
PRIORITY_STEP_TRACE_INDEX = 7,
PRIORITY_STEP_SUCCESOR_TRACE_INDEX = 8,

BEST_LOOP_HEAD = 9,
BEST_SENSITIVE = 10,
BEST_UNTOUCHED = 11,
BEST_IID_TWINS = 12,

NO_SENSITIVITY_IN_INNER_NODE = 13,

START_MONTE_CARLO = 14,
MONTE_CARLO_STEP = 15,
BEST_MONTE_CARLO = 16,

START_MONTE_CARLO_BACKWARD = 17,
MONTE_CARLO_STEP_BACKWARD = 18,
BEST_MONTE_CARLO_BACKWARD = 19,

STARTUP = 20,
};

void flush_node_choosing_data();
void on_node_chosen(branching_node* node, const SELECTION_REASON reason = UNKNOWN);

private:

enum ANALYSIS
Expand Down Expand Up @@ -185,6 +222,21 @@ struct progress_recorder
std::unordered_set<branching_node::guid_type> closed_node_guids;
};

struct node_chossing_data
{
node_chossing_data();

void on_node_chosen(branching_node* node, const SELECTION_REASON reason);

void set_output_dir(std::filesystem::path const& dir);
void clear();
bool empty() const;
void save() const;

std::filesystem::path output_dir;
std::vector<std::tuple<branching_node::guid_type, SELECTION_REASON>> node_guids;
};

progress_recorder();

progress_recorder(progress_recorder const&) = delete;
Expand Down Expand Up @@ -216,6 +268,7 @@ struct progress_recorder
branching_node* leaf;

post_analysis_data post_data;
node_chossing_data node_choosing_data;
};


Expand Down
72 changes: 56 additions & 16 deletions src/fuzzing/src/fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <utility/invariants.hpp>
#include <utility/timeprof.hpp>
#include <map>
#include <iostream>
#include <fstream>

namespace fuzzing {

Expand Down Expand Up @@ -165,7 +167,7 @@ branching_node* fuzzer::primary_coverage_target_branchings::get_best(natural_32
{
best_node = *loop_heads.begin();
++statistics->strategy_primary_loop_head;
recorder().on_strategy_turn_primary_loop_head();
recorder().on_strategy_turn_primary_loop_head(best_node);
return best_node;
}

Expand All @@ -175,7 +177,7 @@ branching_node* fuzzer::primary_coverage_target_branchings::get_best(natural_32
if (!loop_heads.empty())
return get_best(max_input_width);
++statistics->strategy_primary_sensitive;
recorder().on_strategy_turn_primary_sensitive();
recorder().on_strategy_turn_primary_sensitive(best_node);
return best_node;
}

Expand All @@ -184,8 +186,9 @@ branching_node* fuzzer::primary_coverage_target_branchings::get_best(natural_32
{
if (!loop_heads.empty())
return get_best(max_input_width);

++statistics->strategy_primary_untouched;
recorder().on_strategy_turn_primary_untouched();
recorder().on_strategy_turn_primary_untouched(best_node);
return best_node;
}

Expand All @@ -200,7 +203,7 @@ branching_node* fuzzer::primary_coverage_target_branchings::get_best(natural_32
return get_best(max_input_width);
}
++statistics->strategy_primary_iid_twins;
recorder().on_strategy_turn_primary_iid_twins();
recorder().on_strategy_turn_primary_iid_twins(it->second.first);
return it->second.first;
}

Expand Down Expand Up @@ -229,33 +232,66 @@ branching_node* fuzzer::primary_coverage_target_branchings::get_best(
bool operator<(branching_node_with_less_than const& other) const
{
if (node->sensitivity_performed && !other.node->sensitivity_performed)
{
recorder().on_node_chosen(node, fuzzing::progress_recorder::PRIORITY_STEP_NO_SENSITIVITY_PERFORMED);
return true;
}
if (!node->sensitivity_performed && other.node->sensitivity_performed)
return false;

if (node->sensitive_stdin_bits.size() < other.node->sensitive_stdin_bits.size())
{
recorder().on_node_chosen(node, fuzzing::progress_recorder::PRIORITY_STEP_SENSITIVITY_BITS_SIZE);
return true;
}
if (node->sensitive_stdin_bits.size() > other.node->sensitive_stdin_bits.size())
return false;

if (distance_to_central_input_width_class < other.distance_to_central_input_width_class)
{
recorder().on_node_chosen(node, fuzzing::progress_recorder::PRIORITY_STEP_DISTANCE_TO_WIDTH);
return true;
}
if (distance_to_central_input_width_class > other.distance_to_central_input_width_class)
return false;

if (node->get_num_stdin_bytes() < other.node->get_num_stdin_bytes())
{
recorder().on_node_chosen(node, fuzzing::progress_recorder::PRIORITY_STEP_STDIN_SIZE);
return true;
}
if (node->get_num_stdin_bytes() > other.node->get_num_stdin_bytes())
return false;

if (node->trace_index < other.node->trace_index)
{
recorder().on_node_chosen(node, fuzzing::progress_recorder::PRIORITY_STEP_TRACE_INDEX);
return true;
}
if (node->trace_index > other.node->trace_index)
return false;
return node->max_successors_trace_index > other.node->max_successors_trace_index;

if (node->max_successors_trace_index > other.node->max_successors_trace_index)
{
recorder().on_node_chosen(node, fuzzing::progress_recorder::PRIORITY_STEP_SUCCESOR_TRACE_INDEX);
return true;
}
return false;
// return node->max_successors_trace_index > other.node->max_successors_trace_index;
}
private:
branching_node* node;
integer_32_bit distance_to_central_input_width_class;
};

branching_node_with_less_than best{ targets.begin()->first, max_input_width };

if (targets == sensitive)
recorder().on_node_chosen(targets.begin()->first, fuzzing::progress_recorder::SENSITIVITY_PRIORITY_START);

if (targets == untouched)
recorder().on_node_chosen(targets.begin()->first, fuzzing::progress_recorder::UNTOUCHED_PRIORITY_START);

for (auto it = std::next(targets.begin()); it != targets.end(); ++it)
{
branching_node_with_less_than const current{ it->first, max_input_width };
Expand Down Expand Up @@ -382,7 +418,7 @@ void fuzzer::detect_loops_along_path_to_node(
struct loop_exit_props
{
branching_node* exit;
branching_node* successor;
// branching_node* successor;
natural_32_bit index;
};

Expand All @@ -399,7 +435,7 @@ void fuzzer::detect_loops_along_path_to_node(
if (it == pointers_to_branching_stack.end())
{
pointers_to_branching_stack.insert({ node->get_location_id(), (natural_32_bit)branching_stack.size() });
branching_stack.push_back({ node, succ_node, 0U });
branching_stack.push_back({ node, 0U });
}
else
{
Expand All @@ -410,7 +446,7 @@ void fuzzer::detect_loops_along_path_to_node(
if (props.index == 0U)
{
props.index = (natural_32_bit)loops->size();
loops->push_back({ node, props.exit, props.successor });
loops->push_back({ node, props.exit });
}
else
loops->at(props.index).entry = node;
Expand Down Expand Up @@ -452,11 +488,11 @@ void fuzzer::compute_loop_boundaries(
loop_boundaries.push_back(props.entry);
stored.insert(props.entry);
}
if (!stored.contains(props.successor))
{
loop_boundaries.push_back(props.successor);
stored.insert(props.successor);
}
// if (!stored.contains(props.successor))
// {
// loop_boundaries.push_back(props.successor);
// stored.insert(props.successor);
// }
}
std::sort(
loop_boundaries.begin(),
Expand Down Expand Up @@ -671,6 +707,7 @@ branching_node* fuzzer::monte_carlo_search(
if (successor == nullptr)
break;
pivot = successor;
recorder().on_node_chosen(pivot, fuzzing::progress_recorder::MONTE_CARLO_STEP);
}

INVARIANT(pivot != nullptr && pivot->is_open_branching());
Expand Down Expand Up @@ -893,7 +930,7 @@ void fuzzer::generate_next_input(vecb& stdin_bits)
{
case STARTUP:
if (get_performed_driver_executions() == 0U)
return;
return; // Fizzer input is empty
break;

case SENSITIVITY:
Expand Down Expand Up @@ -924,6 +961,7 @@ void fuzzer::generate_next_input(vecb& stdin_bits)
default: { UNREACHABLE(); break; }
}

recorder().flush_node_choosing_data();
do_cleanup();
select_next_state();

Expand Down Expand Up @@ -1451,6 +1489,7 @@ void fuzzer::select_next_state()
winner = right;
else
break;
recorder().on_node_chosen(winner, fuzzing::progress_recorder::NO_SENSITIVITY_IN_INNER_NODE);
}
sensitivity.start(winner, num_driver_executions);
state = SENSITIVITY;
Expand Down Expand Up @@ -1535,7 +1574,7 @@ branching_node* fuzzer::select_iid_coverage_target() const
else
winner = node_and_direction.first;

recorder().on_strategy_turn_monte_carlo_backward();
recorder().on_strategy_turn_monte_carlo_backward(winner);
}
else
{
Expand All @@ -1546,10 +1585,11 @@ branching_node* fuzzer::select_iid_coverage_target() const
entry_branching
);

recorder().on_node_chosen(start_node, fuzzing::progress_recorder::START_MONTE_CARLO);
winner = monte_carlo_search(start_node, histogram, generators, *random_uniform_generator);

++statistics.strategy_monte_carlo;
recorder().on_strategy_turn_monte_carlo();
recorder().on_strategy_turn_monte_carlo(winner);
}

INVARIANT(winner != nullptr);
Expand Down
Loading