check-structures-sanity: fix unknown pointer type not actually dereferencing the pointer

basic attempt at handling overlapping structs
develop
Ben Lubar 2020-03-12 15:20:46 -05:00
parent 1a4c4a5f33
commit d456e3db7a
No known key found for this signature in database
GPG Key ID: 92939677AB59EDA4
4 changed files with 78 additions and 6 deletions

@ -44,6 +44,7 @@ struct CheckedStructure
CheckedStructure(const struct_field_info *);
size_t full_size() const;
const struct_field_info *find_field_at_offset_with_type(size_t, const CheckedStructure &) const;
};
#define MIN_SIZE_FOR_SUGGEST 64
@ -87,6 +88,7 @@ public:
void queue_globals();
bool process_queue();
bool is_in_global(const QueueItem & item);
bool is_valid_dereference(const QueueItem & item, const CheckedStructure & cs, size_t size, bool quiet);
inline bool is_valid_dereference(const QueueItem & item, const CheckedStructure & cs, bool quiet = false)
{

@ -78,15 +78,21 @@ bool Checker::queue_item(const QueueItem & item, const CheckedStructure & cs)
}
}
auto overlap = data.lower_bound(item.ptr);
auto overlap_start = data.lower_bound(item.ptr);
auto overlap_end = data.lower_bound(ptr_end);
while (overlap != overlap_end)
for (auto overlap = overlap_start; overlap != overlap_end; overlap++)
{
// TODO
FAIL("TODO: handle merging structures: " << overlap->second.first << " overlaps " << item.path << " (forward)");
overlap++;
auto offset = uintptr_t(overlap->first) - uintptr_t(item.ptr);
if (!cs.find_field_at_offset_with_type(offset, overlap->second.second))
{
// TODO
FAIL("TODO: handle merging structures: " << overlap->second.first << " overlaps " << item.path << " (forward)");
return false;
}
}
data.erase(overlap_start, overlap_end);
data[item.ptr] = std::make_pair(item.path, cs);
queue.push_back(item);
return true;
@ -326,7 +332,7 @@ void Checker::dispatch_pointer(const QueueItem & item, const CheckedStructure &
auto target = static_cast<pointer_identity *>(cs.identity)->getTarget();
if (!target)
{
check_unknown_pointer(item);
check_unknown_pointer(target_item);
return;
}
@ -362,6 +368,10 @@ void Checker::dispatch_container(const QueueItem & item, const CheckedStructure
{
// TODO: check deque?
}
else if (base_container == "DfArray<void>")
{
// TODO: check DfArray
}
else
{
UNEXPECTED;
@ -486,6 +496,11 @@ void Checker::dispatch_enum(const QueueItem & item, const CheckedStructure & cs)
return;
}
if (is_in_global(item) && enum_value == 0)
{
return;
}
auto enum_name = get_enum_item_key(enum_type, enum_value);
if (!enum_name)
{

@ -107,6 +107,45 @@ size_t CheckedStructure::full_size() const
return size;
}
const struct_field_info *CheckedStructure::find_field_at_offset_with_type(size_t offset, const CheckedStructure & type) const
{
if (!identity)
return nullptr;
if (offset >= identity->byte_size() && offset < full_size())
offset %= identity->byte_size();
else if (offset >= identity->byte_size())
return nullptr;
auto st = dynamic_cast<struct_identity *>(identity);
if (!st)
{
UNEXPECTED;
return nullptr;
}
for (auto p = st; p; p = p->getParent())
{
auto fields = p->getFields();
if (!fields)
continue;
for (auto field = fields; field->mode != struct_field_info::END; field++)
{
if (field->offset > offset)
continue;
if (field->offset == offset && CheckedStructure(field).identity == type.identity)
return field;
if (auto subfield = CheckedStructure(field).find_field_at_offset_with_type(offset - field->offset, type))
return subfield;
}
}
return nullptr;
}
type_identity *Checker::wrap_in_stl_ptr_vector(type_identity *base)
{
static std::map<type_identity *, std::unique_ptr<df::stl_ptr_vector_identity>> wrappers;

@ -1,5 +1,21 @@
#include "check-structures-sanity.h"
bool Checker::is_in_global(const QueueItem & item)
{
auto fields = df::global::_identity.getFields();
for (auto field = fields; field->mode != struct_field_info::END; field++)
{
size_t size = CheckedStructure(field).full_size();
auto start = *reinterpret_cast<const void * const*>(field->offset);
auto offset = uintptr_t(item.ptr) - uintptr_t(start);
if (offset < size)
{
return true;
}
}
return false;
}
bool Checker::is_valid_dereference(const QueueItem & item, const CheckedStructure & cs, size_t size, bool quiet)
{
auto base = const_cast<void *>(item.ptr);