From df8b4894cf6752afebd0939bd6eb44cfbbd7e539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonko=20Sabol=C4=8Dec?= Date: Mon, 14 Jun 2021 16:16:58 +0200 Subject: [PATCH] [fuzzer] Improve memory constraints --- tools/fuzzer/expr_gen.cc | 18 +++++++++++++++--- tools/fuzzer/expr_gen.h | 5 +++++ tools/fuzzer/symbol_table.cc | 16 +++++++++++----- tools/fuzzer/symbol_table.h | 15 ++++++++++----- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/tools/fuzzer/expr_gen.cc b/tools/fuzzer/expr_gen.cc index a3c5a098..721a1f42 100644 --- a/tools/fuzzer/expr_gen.cc +++ b/tools/fuzzer/expr_gen.cc @@ -561,6 +561,12 @@ std::optional 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 {}; @@ -723,9 +729,15 @@ std::optional 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 {}; diff --git a/tools/fuzzer/expr_gen.h b/tools/fuzzer/expr_gen.h index 3113fd34..2edd8f48 100644 --- a/tools/fuzzer/expr_gen.h +++ b/tools/fuzzer/expr_gen.h @@ -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(); diff --git a/tools/fuzzer/symbol_table.cc b/tools/fuzzer/symbol_table.cc index 4223280f..92e0f409 100644 --- a/tools/fuzzer/symbol_table.cc +++ b/tools/fuzzer/symbol_table.cc @@ -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. @@ -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()); } } @@ -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); } } } diff --git a/tools/fuzzer/symbol_table.h b/tools/fuzzer/symbol_table.h index 715c99ec..2d670159 100644 --- a/tools/fuzzer/symbol_table.h +++ b/tools/fuzzer/symbol_table.h @@ -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 { @@ -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)); }