-
Notifications
You must be signed in to change notification settings - Fork 263
Description
Version
2.0.24040
Summary
The generated projection code for interfaces that the metadata declares as required for a runtimeclass assume that QueryInterface never fails. Assuming the metadata is correct in the first place, this is a valid assumption for inproc calls.
However, for cross-process calls the QI can fail even if the metadata is correct and the class really does implement all of the required interfaces. It can fail with E_ACCESSDENIED and a variety of other RPC error codes.
When this happens there is a nullptr crash in the generated consume method. This can be very painful to debug because the HRESULT is lost by the time it crashes.
Reproducible example
IDL file:
namespace CrashRepro
{
// This class declares that it implements another interface but under the covers it actually does
// not. This allows us to test the behavior when QI's that should not fail, do fail.
runtimeclass LiesAboutInheritance : Windows.Foundation.IStringable
{
void StubMethod();
}
}
main.cpp:
#include <winrt/CrashRepro.h>
namespace
{
struct LiesAboutInheritance : public winrt::implements<LiesAboutInheritance, winrt::CrashRepro::ILiesAboutInheritance>
{
LiesAboutInheritance() = default;
void StubMethod() {}
};
}
int main()
{
init_apartment();
auto lies = winrt::make_self<LiesAboutInheritance>().as<winrt::CrashRepro::LiesAboutInheritance>();
FAIL_FAST_IF_NULL(lies);
lies.ToString(); // this line will nullptr crash
}Expected behavior
Ideally it would throw an invalid cast exception that can be caught/handled. Less ideally it should fail with a clear signature.
Actual behavior
There is a nullptr dereference crash. It has unwound enough before crashing that the HRESULT is permanently lost so it is very difficult to debug.
Additional comments
No response