Bug 424522 - dynamic_cast<Okular::ViewerInterface *>(activePart) is null
Summary: dynamic_cast<Okular::ViewerInterface *>(activePart) is null
Status: RESOLVED FIXED
Alias: None
Product: okular
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Gentoo Packages Linux
: NOR normal
Target Milestone: ---
Assignee: Okular developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-07-22 03:18 UTC by 12101111
Modified: 2020-12-13 07:07 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description 12101111 2020-07-22 03:18:01 UTC
SUMMARY

In shell/shell.cpp, Shell::openUrl(),
`dynamic_cast<Okular::ViewerInterface *>(activePart)` is null and cause segmentation fault.

STEPS TO REPRODUCE
(1)
1. Launch okular
2. Open a pdf file
3. Press ctrl-o to open another pdf
4. Okular crash
(2)
1. Set Okular as default pdf viewer
2. Open a pdf file in Dolphin
3. Okular crash

OBSERVED RESULT

backtrace:

#4  Shell::openUrl (this=0x11b99a0, url=..., serializedOptions=...) at ../okular-20.04.3/shell/shell.cpp:276
#5  0x00000000002195e3 in Shell::fileOpen (this=<optimized out>) at ../okular-20.04.3/shell/shell.cpp:501
#6  0x00007f689c89c8b7 in ?? () from /usr/lib64/libQt5Core.so.5
#7  0x00007f689d2e9b4c in QAction::activate(QAction::ActionEvent) () from /usr/lib64/libQt5Widgets.so.5
#8  0x00007f689d2e9959 in QAction::event(QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#9  0x00007f689d2f3260 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#10 0x00007f689d2f46b0 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
#11 0x00007f689c869242 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
#12 0x00007f689cc35015 in QShortcutMap::dispatchEvent(QKeyEvent*) () from /usr/lib64/libQt5Gui.so.5
#13 0x00007f689cc341f3 in QShortcutMap::tryShortcut(QKeyEvent*) () from /usr/lib64/libQt5Gui.so.5
#14 0x00007f689cbe4292 in QWindowSystemInterface::handleShortcutEvent(QWindow*, unsigned long, int, QFlags<Qt::KeyboardModifier>, unsigned int, unsigned int, unsigned int, QString const&, bool, unsigned short) () from /usr/lib64/libQt5Gui.so.5
#15 0x00007f689cc04bdd in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) () from /usr/lib64/libQt5Gui.so.5
#16 0x00007f689cbe895a in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/libQt5Gui.so.5
#17 0x00007f68983db93a in ?? () from /usr/lib64/libQt5XcbQpa.so.5
#18 0x00007f6899290e39 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#19 0x00007f6899291563 in ?? () from /usr/lib64/libglib-2.0.so.0
#20 0x00007f689929181b in g_main_context_iteration () from /usr/lib64/libglib-2.0.so.0
#21 0x00007f689c8c1018 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/libQt5Core.so.5
#22 0x00007f689c865076 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/libQt5Core.so.5
#23 0x00007f689c869831 in QCoreApplication::exec() () from /usr/lib64/libQt5Core.so.5
#24 0x0000000000211c12 in main (argc=1, argv=<optimized out>) at ../okular-20.04.3/shell/main.cpp:113

Add a hack to this function:

diff --git a/shell/shell.cpp b/shell/shell.cpp
index 5d218e28d..f6c84b6d9 100644
--- a/shell/shell.cpp
+++ b/shell/shell.cpp
@@ -257,7 +257,11 @@ void Shell::openUrl(const QUrl &url, const QString &serializedOptions)
                 applyOptionsToPart(activePart, serializedOptions);
                 activePart->openUrl(url);
             } else {
-                if (dynamic_cast<Okular::ViewerInterface *>(activePart)->openNewFilesInTabs()) {
+                Okular::ViewerInterface * vi = dynamic_cast<Okular::ViewerInterface *>(activePart);
+                if ( ! vi) {
+                    printf("vi is null, activePart: %p\n", activePart);
+                }
+                if (vi && vi ->openNewFilesInTabs()) {
                     openNewTab(url, serializedOptions);
                 } else {
                     Shell *newShell = new Shell(serializedOptions);

And recompile it, open some pdfs, the output is:

kf5.kio.kdirmodel: protocol mismatch: "" vs "file"
kf5.kio.kdirmodel: protocol mismatch: "" vs "file"
vi is null, activePart: 0x1d7f840
Settings::instance called after the first use - ignoring
kf5.kio.kdirmodel: protocol mismatch: "" vs "file"
vi is null, activePart: 0x2118470
Settings::instance called after the first use - ignoring
kf5.kio.kdirmodel: protocol mismatch: "" vs "file"
vi is null, activePart: 0x23dcf60
Settings::instance called after the first use - ignoring

So this dynamic_cast is failed.

EXPECTED RESULT

It should not crash

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: 
(available in About System)
KDE Plasma Version: 5.19.3
KDE Frameworks Version: 5.72.0
Qt Version: 5.15.0

ADDITIONAL INFORMATION

I have try gentoo ebuild kde-apps/okular-20.04.3 and source code from git master branch.

I use clang + lld + libc++ as primary toolchain:

CC="clang"
CXX="clang++"
COMMON_FLAGS="-march=skylake -mtune=skylake -O2 -pipe -g"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS} -stdlib=libc++"
LDFLAGS="-fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind"

I think this bug only happend with libcxx and libcxxabi
Comment 1 12101111 2020-07-22 03:40:18 UTC
The bracktrace of (2) is different with (1):

* thread #1, name = 'okular', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
    frame #0: 0x000000000021737d okular`Shell::openDocument(this=0x000000000031ff40, url=0x00007fffffffb3a0, serializedOptions=0x00007fffffffb468) at shell.cpp:226:57
   223      KParts::ReadWritePart* const part = m_tabs[0].part;
   224 
   225      // Return false if we can't open new tabs and the only part is occupied
-> 226      if ( !dynamic_cast<Okular::ViewerInterface*>(part)->openNewFilesInTabs()
   227           && !part->url().isEmpty()
   228           && !ShellUtils::unique(serializedOptions))
   229      {
(lldb) bt
* thread #1, name = 'okular', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  * frame #0: 0x000000000021737d okular`Shell::openDocument(this=0x000000000031ff40, url=0x00007fffffffb3a0, serializedOptions=0x00007fffffffb468) at shell.cpp:226:57
    frame #1: 0x0000000000213ef3 okular`Okular::main(paths=<unavailable>, serializedOptions=0x00007fffffffb468) at okular_main.cpp:181:21
    frame #2: 0x00000000002119f7 okular`main(argc=2, argv=<unavailable>) at main.cpp:100:33
    frame #3: 0x00007ffff5d2fcaa libc.so.6`__libc_start_main + 234
    frame #4: 0x000000000020fc4a okular`_start + 42
Comment 2 Albert Astals Cid 2020-07-22 09:50:04 UTC
This backtrace doesn't really make any sense.

Are you sure you aren't mixing system okular with self compiled okular?
Comment 3 12101111 2020-07-22 14:07:20 UTC
These two backtraces are from Gentoo's okular, and the patch mentioned is for master branch, so the line numbers of `shell.cpp` are not the same.
Comment 4 Albert Astals Cid 2020-07-22 14:38:50 UTC
so you are mixing up 20.04.3 and master? as said, don't do that, that's not going to work
Comment 5 12101111 2020-07-23 06:42:12 UTC
I didn't mix up them. Gentoo Linux don't provide git master version in main tree
Comment 6 12101111 2020-07-23 07:04:00 UTC
I installed kde-apps/okular-20.04.3 as normal, and it crash, so I rebuilt it using CXXFLAGS+="-g" FEATURES="nostrip installsources splitdebug" and got those backtrace.

Then I download source code, edit `shell.cpp`, built (mkdir build && cd build && cmake .. -G Ninja && ninja) and run it (~/okular/build/bin/okular),then got some output.

If running in build directory is not goning to work, I apply the same hack on Gentoo's package, and got the same output:

kf5.kio.kdirmodel: protocol mismatch: "" vs "file"
dynamic_cast<Okular::ViewerInterface *>(activePart) is null,activePart is 0x17a4170
Settings::instance called after the first use - ignoring

The patch file is:

/etc/portage/patches/kde-apps/okular/dynamic_cast_return_null.patch:
diff --git a/shell/shell.cpp b/shell/shell.cpp
index 0bdb710..d18c2d0 100644
--- a/shell/shell.cpp
+++ b/shell/shell.cpp
@@ -223,7 +223,9 @@ bool Shell::openDocument( const QUrl& url, const QString &serializedOptions )
     KParts::ReadWritePart* const part = m_tabs[0].part;

     // Return false if we can't open new tabs and the only part is occupied
-    if ( !dynamic_cast<Okular::ViewerInterface*>(part)->openNewFilesInTabs()
+    Okular::ViewerInterface * vi = dynamic_cast<Okular::ViewerInterface *>(part);
+    if (!vi) printf("dynamic_cast<Okular::ViewerInterface *>(part) is null,part is %p\n",part);
+    if ( vi && !vi->openNewFilesInTabs()
          && !part->url().isEmpty()
          && !ShellUtils::unique(serializedOptions))
     {
@@ -246,7 +248,9 @@ bool Shell::canOpenDocs( int numDocs, int desktop )
       return false;

    KParts::ReadWritePart* const part = m_tabs[0].part;
-   const bool allowTabs = dynamic_cast<Okular::ViewerInterface*>(part)->openNewFilesInTabs();
+   Okular::ViewerInterface * vi = dynamic_cast<Okular::ViewerInterface *>(part);
+   if (!vi) printf("dynamic_cast<Okular::ViewerInterface *>(part) is null,part is %p\n",part);
+   const bool allowTabs = vi && vi ->openNewFilesInTabs();

    if( !allowTabs && (numDocs > 1 || !part->url().isEmpty()) )
       return false;
@@ -273,7 +277,9 @@ void Shell::openUrl( const QUrl & url, const QString &serializedOptions )
             }
             else
             {
-                if( dynamic_cast<Okular::ViewerInterface *>(activePart)->openNewFilesInTabs() )
+                Okular::ViewerInterface * vi = dynamic_cast<Okular::ViewerInterface *>(activePart);
+                if (!vi) printf("dynamic_cast<Okular::ViewerInterface *>(activePart) is null,activePart is %p\n",activePart);
+                if( vi && vi ->openNewFilesInTabs() )
                 {
                     openNewTab( url, serializedOptions );
                 }
Comment 7 Laura David Hurka 2020-07-23 08:30:14 UTC
If Gentoo gives you release/20.04 source code, you will have 20.04 installed.

Then you “download source code”, that will probably give you master source code. If you build that, and don’t `ninja install` it, your master Shell will create 20.04 Parts. Part is located in some/plugin/path/okularpart.so, not in bin/okular.

But since you reproduce the problem with Gentoo package source code, that’s probably not the problem...
Comment 8 Bug Janitor Service 2020-08-07 04:33:09 UTC
Dear Bug Submitter,

This bug has been in NEEDSINFO status with no change for at least
15 days. Please provide the requested information as soon as
possible and set the bug status as REPORTED. Due to regular bug
tracker maintenance, if the bug is still in NEEDSINFO status with
no change in 30 days the bug will be closed as RESOLVED > WORKSFORME
due to lack of needed information.

For more information about our bug triaging procedures please read the
wiki located here:
https://community.kde.org/Guidelines_and_HOWTOs/Bug_triaging

If you have already provided the requested information, please
mark the bug as REPORTED so that the KDE team knows that the bug is
ready to be confirmed.

Thank you for helping us make KDE software even better for everyone!
Comment 9 12101111 2020-08-07 05:14:14 UTC
This issue is still valid
Comment 10 12101111 2020-12-13 07:07:48 UTC
Already fixed in 49c680fd0ea7e98ddc77d455737908ed9b16bd3c