Skip to content

Commit d96cefe

Browse files
authored
[fuzzer] Improve memory constraints (#141)
1 parent cf27bdd commit d96cefe

File tree

4 files changed

+41
-13
lines changed

4 files changed

+41
-13
lines changed

tools/fuzzer/expr_gen.cc

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,12 @@ std::optional<Expr> ExprGenerator::gen_cast_expr_impl(
561561
return {};
562562
}
563563

564+
const auto& memory_constraints = constraints.memory_constraints();
565+
if (!cfg_.valid_pointer_cast_enabled && memory_constraints.must_be_valid() &&
566+
memory_constraints.required_freedom_index() > 0) {
567+
return {};
568+
}
569+
564570
auto maybe_type = gen_type(weights, constraints.type_constraints());
565571
if (!maybe_type.has_value()) {
566572
return {};
@@ -723,9 +729,15 @@ std::optional<Expr> ExprGenerator::gen_member_of_ptr_expr_impl(
723729

724730
Field field = rng_->pick_field(fields);
725731
TypeConstraints new_type_constraints(field.containing_type());
726-
ExprConstraints new_constraints = ExprConstraints(
727-
new_type_constraints.make_pointer_constraints(),
728-
memory_constraints.from_member_of(constraints.must_be_lvalue(), 1));
732+
// If the field is a reference or a virtually inherited field, assume a read
733+
// from memory.
734+
MemoryConstraints new_memory_constraints =
735+
field.is_reference_or_virtual()
736+
? MemoryConstraints(true, 1)
737+
: memory_constraints.from_member_of(constraints.must_be_lvalue(), 1);
738+
ExprConstraints new_constraints =
739+
ExprConstraints(new_type_constraints.make_pointer_constraints(),
740+
std::move(new_memory_constraints));
729741
auto maybe_expr = gen_with_weights(weights, std::move(new_constraints));
730742
if (!maybe_expr.has_value()) {
731743
return {};

tools/fuzzer/expr_gen.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ struct GenConfig {
147147
// Probability that sizeof will take a type as a argument.
148148
float sizeof_gen_type_prob = 0.3f;
149149

150+
// A cast such as `((AnotherStruct*)struct_ptr)->field` isn't allowed. Setting
151+
// this flag to false avoids casting between different pointer types if read
152+
// from memory is expected.
153+
bool valid_pointer_cast_enabled = false;
154+
150155
BinOpMask bin_op_mask = BinOpMask::all_set();
151156
UnOpMask un_op_mask = UnOpMask::all_set();
152157

tools/fuzzer/symbol_table.cc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,17 +243,21 @@ class ClassAnalyzer {
243243
std::string name;
244244
Type type;
245245
uint32_t id;
246+
bool is_reference;
246247
bool is_virtual; // Is it a virtually inherited field?
247248

248-
FieldInfo(std::string name, Type type, uint32_t id, bool is_virtual = false)
249+
FieldInfo(std::string name, Type type, uint32_t id, bool is_reference,
250+
bool is_virtual = false)
249251
: name(std::move(name)),
250252
type(std::move(type)),
251253
id(id),
254+
is_reference(is_reference),
252255
is_virtual(is_virtual) {}
253256

254257
friend bool operator==(const FieldInfo& lhs, const FieldInfo& rhs) {
255-
return lhs.id == rhs.id && lhs.is_virtual == rhs.is_virtual &&
256-
lhs.name == rhs.name && lhs.type == rhs.type;
258+
return lhs.id == rhs.id && lhs.is_reference == rhs.is_reference &&
259+
lhs.is_virtual == rhs.is_virtual && lhs.name == rhs.name &&
260+
lhs.type == rhs.type;
257261
}
258262

259263
// Needed for std::unordered_set.
@@ -310,7 +314,7 @@ class ClassAnalyzer {
310314
auto maybe_type = convert_type(field.GetType(), ignore_qualified_types_);
311315
if (maybe_type.has_value()) {
312316
fields.emplace(fix_name(field.GetName()), std::move(maybe_type.value()),
313-
next_field_id());
317+
next_field_id(), field.GetType().IsReferenceType());
314318
}
315319
}
316320

@@ -398,7 +402,9 @@ ClassAnalyzer load_tagged_types(SymbolTable& symtab, lldb::SBFrame& frame,
398402
const auto& info = classes.get_class_info(type);
399403
for (const auto& field : info.fields()) {
400404
if (info.is_unique_field_name(field.name)) {
401-
symtab.add_field(tagged_type, field.name, field.type);
405+
bool reference_or_virtual = field.is_reference || field.is_virtual;
406+
symtab.add_field(tagged_type, field.name, field.type,
407+
reference_or_virtual);
402408
}
403409
}
404410
}

tools/fuzzer/symbol_table.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,20 @@ struct VariableFreedomPair {
4242

4343
class Field {
4444
public:
45-
Field(TaggedType containing_type, std::string name)
46-
: containing_type_(std::move(containing_type)), name_(std::move(name)) {}
45+
Field(TaggedType containing_type, std::string name,
46+
bool is_reference_or_virtual = false)
47+
: containing_type_(std::move(containing_type)),
48+
name_(std::move(name)),
49+
is_reference_or_virtual_(is_reference_or_virtual) {}
4750

4851
const TaggedType& containing_type() const { return containing_type_; }
4952
const std::string& name() const { return name_; }
53+
bool is_reference_or_virtual() const { return is_reference_or_virtual_; }
5054

5155
private:
5256
TaggedType containing_type_;
5357
std::string name_;
58+
bool is_reference_or_virtual_;
5459
};
5560

5661
class Function {
@@ -100,9 +105,9 @@ class SymbolTable {
100105
}
101106

102107
void add_field(TaggedType containing_type, std::string field_name,
103-
Type field_type) {
104-
fields_by_type_[std::move(field_type)].emplace_back(containing_type,
105-
std::move(field_name));
108+
Type field_type, bool reference_or_virtual) {
109+
fields_by_type_[std::move(field_type)].emplace_back(
110+
containing_type, std::move(field_name), reference_or_virtual);
106111

107112
tagged_types_.insert(std::move(containing_type));
108113
}

0 commit comments

Comments
 (0)