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

@ -107,6 +107,45 @@ size_t CheckedStructure::full_size() const
return size; 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) 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; static std::map<type_identity *, std::unique_ptr<df::stl_ptr_vector_identity>> wrappers;

@ -1,5 +1,21 @@
#include "check-structures-sanity.h" #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) bool Checker::is_valid_dereference(const QueueItem & item, const CheckedStructure & cs, size_t size, bool quiet)
{ {
auto base = const_cast<void *>(item.ptr); auto base = const_cast<void *>(item.ptr);