Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions Source/com/Administrator.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,14 +401,51 @@ namespace RPC {
}

private:
// Convert a ProxyType<IIPC> to ProxyType<InvokeMessage> using
// static_cast rather than dynamic_cast.
//
// On macOS, Apple Clang unconditionally emits typeinfo for
// implicit template instantiations as "weak private external"
// (hidden), regardless of -fvisibility settings or explicit
// visibility annotations. Apple's libc++ compares typeinfo by
// pointer only for hidden symbols (no strcmp fallback like
// libstdc++ on Linux), so dynamic_cast across dylib boundaries
// fails for template types like IPCMessageType.
//
// The label check (IIPC::Label() == InvokeMessage::Id()) provides
// the same runtime type guarantee that dynamic_cast would, and
// static_cast correctly adjusts for the multiple-inheritance
// layout (IPCMessageType inherits both IIPC and IReferenceCounted).
static Core::ProxyType<InvokeMessage> ExtractInvokeMessage(const Core::ProxyType<Core::IIPC>& data)
{
Core::ProxyType<InvokeMessage> message(data);
ASSERT(message.IsValid() == true);
if (data.IsValid() == false) {
return Core::ProxyType<InvokeMessage>();
}

Core::IIPC* raw = const_cast<Core::IIPC*>(data.operator->());
ASSERT(raw->Label() == InvokeMessage::Id());

if (raw->Label() != InvokeMessage::Id()) {
return Core::ProxyType<InvokeMessage>();
}

InvokeMessage* message = static_cast<InvokeMessage*>(raw);
if (message->Parameters().IsValid() == false) {
message = Core::ProxyType<InvokeMessage>();
return Core::ProxyType<InvokeMessage>();
}
return message;
return Core::ProxyType<InvokeMessage>(
static_cast<Core::IReferenceCounted&>(*message), *message);
}
static Core::ProxyType<InvokeMessage> ToInvokeMessage(const Core::ProxyType<Core::IIPC>& data)
{
if ((data.IsValid() == false) || (data->Label() != InvokeMessage::Id())) {
return Core::ProxyType<InvokeMessage>();
}

InvokeMessage* message =
static_cast<InvokeMessage*>(const_cast<Core::IIPC*>(data.operator->()));
return Core::ProxyType<InvokeMessage>(
static_cast<Core::IReferenceCounted&>(*message), *message);
}

public:
Expand Down Expand Up @@ -447,7 +484,7 @@ namespace RPC {
}
string Identifier() const override {
string identifier;
Core::ProxyType<InvokeMessage> message(_message);
Core::ProxyType<InvokeMessage> message(ToInvokeMessage(_message));
if (message.IsValid() == false) {
identifier = _T("{ \"type\": \"COMRPC\" }");
}
Expand Down
2 changes: 1 addition & 1 deletion Source/com/Communicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ namespace RPC {
// Message delivered and responded on....
RPC::AnnounceMessage* announceMessage = static_cast<RPC::AnnounceMessage*>(&element);

ASSERT(dynamic_cast<RPC::AnnounceMessage*>(&element) != nullptr);
ASSERT(element.Label() == RPC::AnnounceMessage::Id());

if (announceMessage->Response().IsSet() == true) {
string jsonMessagingCategories(announceMessage->Response().MessagingCategories());
Expand Down
18 changes: 16 additions & 2 deletions Source/com/Communicator.h
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,14 @@ namespace RPC {
public:
void Procedure(Core::IPCChannel& channel, Core::ProxyType<Core::IIPC>& data) override {

Core::ProxyType<AnnounceMessage> message(data);
// Use static_cast + label check instead of dynamic_cast
// to avoid cross-dylib RTTI failure on macOS (see
// Administrator.h ExtractInvokeMessage for details).
ASSERT(data.IsValid() && data->Label() == AnnounceMessage::Id());
AnnounceMessage* rawMsg =
static_cast<AnnounceMessage*>(const_cast<Core::IIPC*>(data.operator->()));
Core::ProxyType<AnnounceMessage> message(
static_cast<Core::IReferenceCounted&>(*rawMsg), *rawMsg);

ASSERT(message.IsValid() == true);
ASSERT(dynamic_cast<Client*>(&channel) != nullptr);
Expand Down Expand Up @@ -1842,7 +1849,14 @@ POP_WARNING()
{
// Oke, see if we can reference count the IPCChannel
Core::ProxyType<Core::IPCChannel> refChannel(channel);
Core::ProxyType<RPC::AnnounceMessage> message(data);

// Use static_cast + label check instead of dynamic_cast
// (see Administrator.h ExtractInvokeMessage for rationale).
ASSERT(data.IsValid() && data->Label() == RPC::AnnounceMessage::Id());
RPC::AnnounceMessage* rawMsg =
static_cast<RPC::AnnounceMessage*>(const_cast<Core::IIPC*>(data.operator->()));
Core::ProxyType<RPC::AnnounceMessage> message(
static_cast<Core::IReferenceCounted&>(*rawMsg), *rawMsg);

ASSERT(refChannel.IsValid());

Expand Down
Loading