summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2023-01-04 12:14:22 +0100
committerStephan Bergmann <sbergman@redhat.com>2023-01-04 13:49:58 +0000
commitef533553559fe09b4afab651fc692885d1acf4ed (patch)
treebbd17cba9c5253ddbe62250efa63c3d169156180 /bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
parent146eb1aa750a7612deb9d3e1825a7a2e1256bd4d (diff)
Rudimentary support for dynamic_cast on UNO proxy objects
<https://gerrit.libreoffice.org/c/core/+/144139> "New loplugin:unocast" had argued that uses of dynamic_cast from a UNO interface type are broken in general (because if the source object is a proxy from the C*+ UNO bridge, its vtable's RTTI slot will normally not be set up, which can cause a crash), and should be replaced with uses of XUnoTunnel. Which the various recent "loplugin:unocast (...)" commits started to do. However, it became clear that that is not the most ideal way forward: For one, getting more and more implementations of XUnoTunnel::getSomething into existing class hierarchies is error prone, as each such implementation must manually delegate to all its base class implementations. For another, uses of comphelper::getFromUnoTunnel (which often needs to do a queryInterface to XUnoTunnel first) are easily more expensive than uses of dynamic_cast. Thanks to Noel, the insight here is that for the use case of a dynamic_cast from a UNO interface type to a local C++ class type, and if the source object is a proxy, it is sufficient that the dynamic_cast will not crash. It will necessarily always return null (as the proxy will never be the implementation of a local C++ class type), so it is sufficient to fill the RTTI slots of the proxies' vtables with dummy values. That avoids having to set up proper RTTI for those potentially multiple-inheritance proxy types. (And with this in place, all those recent "loplugin:unocast (...)" commits can be reverted again in a next step.) I verified the changes for the gcc3_linux_aarch64 (on macOS), gcc3_linux_intel, gcc3_linux_x86-64, gcc3_macosx_x86-64, msvc_win32_intel, and msvc_win32_x86-64 bridges. The changes for all the other bridges were done blindly. (For gcc3_linux_x86-64, which already conditionally supported proper RTTI for UBSan, setting the offset-to-top slot to non-zero had to be made conditional too, as the dummy ProxyRtti will always pretend to be a full class rather than a potential base class that could have a non-zero offset-to-top value. For msvc_win32_*, it turned out that the existing code to set up dummy XInterface RTTI (which was there for reasons lost to history) was broken.) Change-Id: Iec4b8067d26b14b6fb02c2fdd15e1eee20919590 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145038 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx')
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx15
1 files changed, 13 insertions, 2 deletions
diff --git a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
index 21de11b5ea36..9ba5af012443 100644
--- a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
@@ -16,6 +16,11 @@
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+
+#include <sal/config.h>
+
+#include <typeinfo>
+
#include <com/sun/star/uno/RuntimeException.hpp>
#include <sal/log.hxx>
#include <uno/data.h>
@@ -457,7 +462,7 @@ namespace
}
}
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
bridges::cpp_uno::shared::VtableFactory::Slot *
bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -471,6 +476,12 @@ std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(
return (slotCount + 2) * sizeof (Slot);
}
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
bridges::cpp_uno::shared::VtableFactory::Slot *
bridges::cpp_uno::shared::VtableFactory::initializeBlock(
void * block, sal_Int32 slotCount, sal_Int32,
@@ -478,7 +489,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
{
Slot * slots = mapBlockToVtable(block);
slots[-2].fn = 0;
- slots[-1].fn = 0;
+ slots[-1].fn = &typeid(ProxyRtti);
return slots + slotCount;
}