From 269b3cb8ebb30a42d11e3fc6aa9669afc7c4c972 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Mon, 2 Mar 2020 15:34:29 -0600 Subject: [PATCH] add support for finding vtable pointers to check-structures-sanity update structures --- library/xml | 2 +- plugins/devel/check-structures-sanity.cpp | 24 +++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/library/xml b/library/xml index 24ed65035..9df961c03 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 24ed650356467b48ee12db9b22deb0528430d375 +Subproject commit 9df961c0382cfdf052dfac2315c39a7260c497c5 diff --git a/plugins/devel/check-structures-sanity.cpp b/plugins/devel/check-structures-sanity.cpp index e41c3948c..6c9f5fb49 100644 --- a/plugins/devel/check-structures-sanity.cpp +++ b/plugins/devel/check-structures-sanity.cpp @@ -216,7 +216,7 @@ private: #endif bool check_access(const ToCheck &, void *, type_identity *); 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_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 *); @@ -535,20 +535,20 @@ bool Checker::check_access(const ToCheck & item, void *base, type_identity *iden #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 *))) - return false; + return nullptr; char **info = *(reinterpret_cast(vtable) - 1); #ifdef WIN32 if (!check_access(item, PTR_ADD(info, 12), identity, 4)) - return false; + return nullptr; #ifdef DFHACK64 void *base; if (!RtlPcToFileHeader(info, &base)) - return false; + return nullptr; char *typeinfo = reinterpret_cast(base) + reinterpret_cast(info)[3]; char *name = typeinfo + 16; @@ -557,7 +557,7 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id #endif #else if (!check_access(item, info + 1, identity, sizeof(void *))) - return false; + return nullptr; char *name = *(info + 1); #endif @@ -571,7 +571,7 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id if (!range.valid || !range.read) { FAIL("pointer to invalid memory range"); - return false; + return nullptr; } bool letter = false; @@ -579,7 +579,7 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id { if (!range.isInRange(p)) { - return false; + return nullptr; } if (*p >= 'a' && *p <= 'z') @@ -588,12 +588,12 @@ bool Checker::check_vtable(const ToCheck & item, void *vtable, type_identity *id } else if (!*p) { - return letter; + return letter ? name : nullptr; } } } - return false; + return nullptr; } 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() << ")"); } #endif + else if (auto vtable_name = check_vtable(item, item.ptr, df::identity_traits::get())) + { + FAIL("pointer to a vtable: " << vtable_name); + } else { FAIL("pointer to memory with no size information");