add support for finding vtable pointers to check-structures-sanity

update structures
develop
Ben Lubar 2020-03-02 15:34:29 -06:00
parent 0024457167
commit 269b3cb8eb
No known key found for this signature in database
GPG Key ID: 92939677AB59EDA4
2 changed files with 15 additions and 11 deletions

@ -1 +1 @@
Subproject commit 24ed650356467b48ee12db9b22deb0528430d375 Subproject commit 9df961c0382cfdf052dfac2315c39a7260c497c5

@ -216,7 +216,7 @@ private:
#endif #endif
bool check_access(const ToCheck &, void *, type_identity *); bool check_access(const ToCheck &, void *, type_identity *);
bool check_access(const ToCheck &, void *, type_identity *, size_t); bool check_access(const ToCheck &, void *, type_identity *, size_t);
bool check_vtable(const ToCheck &, void *, type_identity *); const char *check_vtable(const ToCheck &, void *, type_identity *);
void queue_field(ToCheck &&, const struct_field_info *); void queue_field(ToCheck &&, const struct_field_info *);
void queue_static_array(const ToCheck &, void *, type_identity *, size_t, bool = false, enum_identity * = nullptr); void queue_static_array(const ToCheck &, void *, type_identity *, size_t, bool = false, enum_identity * = nullptr);
bool maybe_queue_union(const ToCheck &, const struct_field_info *, const struct_field_info *); bool maybe_queue_union(const ToCheck &, const struct_field_info *, const struct_field_info *);
@ -535,20 +535,20 @@ bool Checker::check_access(const ToCheck & item, void *base, type_identity *iden
#undef FAIL_PTR #undef FAIL_PTR
} }
bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *identity) const char *Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *identity)
{ {
if (!check_access(item, PTR_ADD(vtable, -ptrdiff_t(sizeof(void *))), identity, sizeof(void *))) if (!check_access(item, PTR_ADD(vtable, -ptrdiff_t(sizeof(void *))), identity, sizeof(void *)))
return false; return nullptr;
char **info = *(reinterpret_cast<char ***>(vtable) - 1); char **info = *(reinterpret_cast<char ***>(vtable) - 1);
#ifdef WIN32 #ifdef WIN32
if (!check_access(item, PTR_ADD(info, 12), identity, 4)) if (!check_access(item, PTR_ADD(info, 12), identity, 4))
return false; return nullptr;
#ifdef DFHACK64 #ifdef DFHACK64
void *base; void *base;
if (!RtlPcToFileHeader(info, &base)) if (!RtlPcToFileHeader(info, &base))
return false; return nullptr;
char *typeinfo = reinterpret_cast<char *>(base) + reinterpret_cast<int32_t *>(info)[3]; char *typeinfo = reinterpret_cast<char *>(base) + reinterpret_cast<int32_t *>(info)[3];
char *name = typeinfo + 16; char *name = typeinfo + 16;
@ -557,7 +557,7 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id
#endif #endif
#else #else
if (!check_access(item, info + 1, identity, sizeof(void *))) if (!check_access(item, info + 1, identity, sizeof(void *)))
return false; return nullptr;
char *name = *(info + 1); char *name = *(info + 1);
#endif #endif
@ -571,7 +571,7 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id
if (!range.valid || !range.read) if (!range.valid || !range.read)
{ {
FAIL("pointer to invalid memory range"); FAIL("pointer to invalid memory range");
return false; return nullptr;
} }
bool letter = false; bool letter = false;
@ -579,7 +579,7 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id
{ {
if (!range.isInRange(p)) if (!range.isInRange(p))
{ {
return false; return nullptr;
} }
if (*p >= 'a' && *p <= 'z') if (*p >= 'a' && *p <= 'z')
@ -588,12 +588,12 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id
} }
else if (!*p) else if (!*p)
{ {
return letter; return letter ? name : nullptr;
} }
} }
} }
return false; return nullptr;
} }
void Checker::queue_field(ToCheck && item, const struct_field_info *field) void Checker::queue_field(ToCheck && item, const struct_field_info *field)
@ -834,6 +834,10 @@ void Checker::check_dispatch(ToCheck & item)
FAIL("untyped pointer is actually stl-string with value \"" << *str << "\" (length " << str->length() << ")"); FAIL("untyped pointer is actually stl-string with value \"" << *str << "\" (length " << str->length() << ")");
} }
#endif #endif
else if (auto vtable_name = check_vtable(item, item.ptr, df::identity_traits<void *>::get()))
{
FAIL("pointer to a vtable: " << vtable_name);
}
else else
{ {
FAIL("pointer to memory with no size information"); FAIL("pointer to memory with no size information");