Skip to content

Commit fd19e8d

Browse files
committed
Improve pointer type recovery and suppress pure-virtual no-return in vtables.
1 parent f71bf68 commit fd19e8d

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

plugins/rtti/itanium.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,15 @@ std::optional<VirtualFunctionTableInfo> ItaniumRTTIProcessor::ProcessVFT(uint64_
647647
if (pos != std::string::npos)
648648
vFuncName = vFuncName.substr(pos + 2);
649649

650+
// A pure-virtual vtable slot may point to __cxa_pure_virtual, whose analyzed type is
651+
// parameterless and no-return. That is the type of the placeholder target, not the virtual
652+
// method the slot represents: a slot should describe the polymorphic operation, not the
653+
// concrete function currently occupying it. Propagating that type into the vtable would
654+
// wrongly make dispatch through the slot no-return. This heuristically recognizes the
655+
// characteristic __cxa_pure_virtual shape (empty parameters, no-return) and treats it as
656+
// unknown; it does not prove the target is __cxa_pure_virtual.
657+
if (vFuncType && vFuncType->GetClass() == FunctionTypeClass && vFuncType->GetParameters().empty() && !vFuncType->CanReturn().GetValue())
658+
vFuncType = Type::VoidType();
650659
auto vFuncOffset = vFuncIdx * addrSize;
651660
vftBuilder.AddMemberAtOffset(
652661
Type::PointerType(addrSize, vFuncType, true), vFuncName, vFuncOffset);

plugins/rtti/microsoft.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
528528
// Until https://github.com/Vector35/binaryninja-api/issues/5982 is fixed
529529
auto vftSize = virtualFunctions.size() * addrSize;
530530
vftBuilder.SetWidth(vftSize);
531-
531+
532532
if (baseClassInfo.has_value() && baseClassInfo->vft.has_value())
533533
{
534534
if (baseClassInfo->vft->virtualFunctions.size() <= virtualFunctions.size())
@@ -572,6 +572,15 @@ std::optional<VirtualFunctionTableInfo> MicrosoftRTTIProcessor::ProcessVFT(uint6
572572
auto vFuncOffset = vFuncIdx * addrSize;
573573
// We have access to a backing function type, use it, otherwise void!
574574
auto vFuncType = vFunc.has_value() ? vFunc.value()->GetType() : Type::VoidType();
575+
// A pure-virtual vtable slot may point to _purecall, whose analyzed type is parameterless and
576+
// no-return. That is the type of the placeholder target, not the virtual method the slot
577+
// represents: a slot should describe the polymorphic operation, not the concrete function
578+
// currently occupying it. Propagating that type into the vtable would wrongly make dispatch
579+
// through the slot no-return. This heuristically recognizes the characteristic _purecall shape
580+
// (empty parameters, no-return) and treats it as unknown; it does not prove the target is
581+
// _purecall.
582+
if (vFuncType && vFuncType->GetClass() == FunctionTypeClass && vFuncType->GetParameters().empty() && !vFuncType->CanReturn().GetValue())
583+
vFuncType = Type::VoidType();
575584
vftBuilder.AddMemberAtOffset(
576585
Type::PointerType(addrSize, vFuncType, true), vFuncName, vFuncOffset);
577586
vFuncIdx++;

0 commit comments

Comments
 (0)