Skip to content
Merged
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
18 changes: 15 additions & 3 deletions tools/fuzzer/expr_gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,12 @@ std::optional<Expr> ExprGenerator::gen_cast_expr_impl(
return {};
}

const auto& memory_constraints = constraints.memory_constraints();
if (!cfg_.valid_pointer_cast_enabled && memory_constraints.must_be_valid() &&
memory_constraints.required_freedom_index() > 0) {
return {};
}

auto maybe_type = gen_type(weights, constraints.type_constraints());
if (!maybe_type.has_value()) {
return {};
Expand Down Expand Up @@ -723,9 +729,15 @@ std::optional<Expr> ExprGenerator::gen_member_of_ptr_expr_impl(

Field field = rng_->pick_field(fields);
TypeConstraints new_type_constraints(field.containing_type());
ExprConstraints new_constraints = ExprConstraints(
new_type_constraints.make_pointer_constraints(),
memory_constraints.from_member_of(constraints.must_be_lvalue(), 1));
// If the field is a reference or a virtually inherited field, assume a read
// from memory.
MemoryConstraints new_memory_constraints =
field.is_reference_or_virtual()
? MemoryConstraints(true, 1)
: memory_constraints.from_member_of(constraints.must_be_lvalue(), 1);
ExprConstraints new_constraints =
ExprConstraints(new_type_constraints.make_pointer_constraints(),
std::move(new_memory_constraints));
auto maybe_expr = gen_with_weights(weights, std::move(new_constraints));
if (!maybe_expr.has_value()) {
return {};
Expand Down
5 changes: 5 additions & 0 deletions tools/fuzzer/expr_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ struct GenConfig {
// Probability that sizeof will take a type as a argument.
float sizeof_gen_type_prob = 0.3f;

// A cast such as `((AnotherStruct*)struct_ptr)->field` isn't allowed. Setting
// this flag to false avoids casting between different pointer types if read
// from memory is expected.
bool valid_pointer_cast_enabled = false;

BinOpMask bin_op_mask = BinOpMask::all_set();
UnOpMask un_op_mask = UnOpMask::all_set();

Expand Down
16 changes: 11 additions & 5 deletions tools/fuzzer/symbol_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -243,17 +243,21 @@ class ClassAnalyzer {
std::string name;
Type type;
uint32_t id;
bool is_reference;
bool is_virtual; // Is it a virtually inherited field?

FieldInfo(std::string name, Type type, uint32_t id, bool is_virtual = false)
FieldInfo(std::string name, Type type, uint32_t id, bool is_reference,
bool is_virtual = false)
: name(std::move(name)),
type(std::move(type)),
id(id),
is_reference(is_reference),
is_virtual(is_virtual) {}

friend bool operator==(const FieldInfo& lhs, const FieldInfo& rhs) {
return lhs.id == rhs.id && lhs.is_virtual == rhs.is_virtual &&
lhs.name == rhs.name && lhs.type == rhs.type;
return lhs.id == rhs.id && lhs.is_reference == rhs.is_reference &&
lhs.is_virtual == rhs.is_virtual && lhs.name == rhs.name &&
lhs.type == rhs.type;
}

// Needed for std::unordered_set.
Expand Down Expand Up @@ -310,7 +314,7 @@ class ClassAnalyzer {
auto maybe_type = convert_type(field.GetType(), ignore_qualified_types_);
if (maybe_type.has_value()) {
fields.emplace(fix_name(field.GetName()), std::move(maybe_type.value()),
next_field_id());
next_field_id(), field.GetType().IsReferenceType());
}
}

Expand Down Expand Up @@ -398,7 +402,9 @@ ClassAnalyzer load_tagged_types(SymbolTable& symtab, lldb::SBFrame& frame,
const auto& info = classes.get_class_info(type);
for (const auto& field : info.fields()) {
if (info.is_unique_field_name(field.name)) {
symtab.add_field(tagged_type, field.name, field.type);
bool reference_or_virtual = field.is_reference || field.is_virtual;
symtab.add_field(tagged_type, field.name, field.type,
reference_or_virtual);
}
}
}
Expand Down
15 changes: 10 additions & 5 deletions tools/fuzzer/symbol_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,20 @@ struct VariableFreedomPair {

class Field {
public:
Field(TaggedType containing_type, std::string name)
: containing_type_(std::move(containing_type)), name_(std::move(name)) {}
Field(TaggedType containing_type, std::string name,
bool is_reference_or_virtual = false)
: containing_type_(std::move(containing_type)),
name_(std::move(name)),
is_reference_or_virtual_(is_reference_or_virtual) {}

const TaggedType& containing_type() const { return containing_type_; }
const std::string& name() const { return name_; }
bool is_reference_or_virtual() const { return is_reference_or_virtual_; }

private:
TaggedType containing_type_;
std::string name_;
bool is_reference_or_virtual_;
};

class Function {
Expand Down Expand Up @@ -100,9 +105,9 @@ class SymbolTable {
}

void add_field(TaggedType containing_type, std::string field_name,
Type field_type) {
fields_by_type_[std::move(field_type)].emplace_back(containing_type,
std::move(field_name));
Type field_type, bool reference_or_virtual) {
fields_by_type_[std::move(field_type)].emplace_back(
containing_type, std::move(field_name), reference_or_virtual);

tagged_types_.insert(std::move(containing_type));
}
Expand Down