Expand dynamic cast hierarchy.
AbandonedPublic

Authored by adridg on Jan 3 2020, 2:04 PM.

Details

Reviewers
None
Summary

On FreeBSD, with Clang 8 at least, the one-step dynamic cast
from QAbstractItemModel* down to KeyListModelInterface*
returns nullptr. Doing it in two steps (possibly because the
interface is the second base class?) fixes the casts and returns
the correctly-cast pointer.

Test Plan

This is related to
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242670
https://bugs.kde.org/show_bug.cgi?id=415168

This manifests itself in Kleopatra by, for instance, the *Details*
RMB item to be disabled, and double-clicking on a key doing nothing
(because, internally, the model was returning nullptr, and then
there's zero keys when it gets into DetailsCommand::doStart().

Diff Detail

Repository
R168 Kleopatra
Branch
fix-freebsd
Lint
No Linters Available
Unit
No Unit Test Coverage
Build Status
Buildable 20578
Build 20596: arc lint + arc unit
adridg created this revision.Jan 3 2020, 2:04 PM
Restricted Application added a project: KDE PIM. · View Herald TranscriptJan 3 2020, 2:04 PM
Restricted Application added a subscriber: kde-pim. · View Herald Transcript
adridg requested review of this revision.Jan 3 2020, 2:04 PM
adridg updated this revision to Diff 72686.Jan 3 2020, 2:08 PM
  • Expand dynamic cast hierarchy. This is another situation where a 2-stage dynamic_cast<> doesn't work, leading to a nullptr dereference.

I have a theory where this might come from, but I can't verify this here (problem is not reproduceable): KeyListModelInterface is in a different lib and is not exported (all inline), but has a vtable and RTTI data. This results in the RTTI data being duplicated in every lib/executable (as there is no exported one that can be shared), which means there's two different RTTI instances for the kleo binary and libkleo, dynamic_cast picks the wrong one in your setup, and fails. The second level cast to KeyRearrangeColumnsProxyModel (in libkleo, but exported) makes it cast from a type in the same lib, which then apparently makes it pick the right RTTI instance and succeed.

If this is right, I'd say the correct fix is exporting KeyListModelInterface, and de-inlining its virtual dtor, I'm not sure that the double cast fix is guaranteed to always work.

anthonyfieroni added a subscriber: anthonyfieroni.EditedJan 4 2020, 12:21 PM

That's bug in Clang, dynamic_cast does not do anything to depth and it should not depend of that. You can try qobject_cast if it behave normal can be merged.

@aheinecke patch in bug 415168 fixes the issue by doing the single-RTTI-exported that Volker talks about.

adridg abandoned this revision.Jun 1 2020, 3:39 PM