Check for nullptr in indexForNode
AbandonedPublic

Authored by jtamate on Mar 3 2018, 11:29 AM.

Details

Reviewers
dfaure
Group Reviewers
Frameworks
Summary

CCBUG: 390288
Checking for nullptr will avoid the crash and return an empty
QModelIndex.

Test Plan

Ask @Valdo if the bug can be reproduced.

Diff Detail

Repository
R241 KIO
Branch
kate (branched from master)
Lint
No Linters Available
Unit
No Unit Test Coverage
jtamate created this revision.Mar 3 2018, 11:29 AM
Restricted Application added a project: Frameworks. · View Herald TranscriptMar 3 2018, 11:29 AM
jtamate requested review of this revision.Mar 3 2018, 11:29 AM

It would be much better to fix those two issues instead...

kf5.kio.core: Refilling KProtocolInfoFactory cache in the hope to find ""
(which sounds like a wrongly constructed URL with no scheme)

kf5.kio.widgets: Items emitted in directory QUrl("smb://") but that directory isn't in KDirModel! Root directory: QUrl("smb:///")
(which might or might not be a consequence of the previous issue)

I tried testing

kdialog --getexistingdirectory smb://

but this gives an error here "Unable to find any workgroups in your local network." even with samba started locally. Don't know why.

I tried testing

kdialog --getexistingdirectory smb://

but this gives an error here "Unable to find any workgroups in your local network." even with samba started locally. Don't know why.

I get always a crash trying kdialog --getexistingdirectory smb://, only executed directly or under valgrind, but not under gdb when I get that message also.

8150== Process terminating with default action of signal 11 (SIGSEGV)

8150== Access not within mapped region at address 0x28

8150== at 0x62701D6: QObject::isWidgetType() const (qobject.h:147)

8150== by 0x627022C: QWidget* qobject_cast<QWidget*>(QObject*) (qwidget.h:741)

8150== by 0x627072B: QtPrivate::QVariantValueHelper<QWidget*>::object(QVariant const&) (qvariant.h:709)

8150== by 0x62704BD: QtPrivate::ObjectInvoker<QtPrivate::QVariantValueHelper<QWidget*>, QVariant const&, QWidget*>::invoke(QVariant const&) (qvariant.h:102)

8150== by 0x627037B: QWidget* qvariant_cast<QWidget*>(QVariant const&) (qvariant.h:835)

8150== by 0x62702D5: QWidget* QVariant::value<QWidget*>() const (qvariant.h:352)

8150== by 0x626FF64: KJobWidgets::window(KJob*) (kjobwidgets.cpp:35)

8150== by 0x6268028: KDialogJobUiDelegate::window() const (kdialogjobuidelegate.cpp:144)

8150== by 0x62680E6: KDialogJobUiDelegate::showErrorMessage() (kdialogjobuidelegate.cpp:162)

8150== by 0x4F48236: KDirLister::handleError(KIO::Job*) (kdirlister.cpp:81)

8150== by 0x5F9F573: KCoreDirListerCache::slotResult(KJob*) (kcoredirlister.cpp:1334)

8150== by 0x5FAAC6E: KCoreDirListerCache::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (moc_kcoredirlister_p.cpp:136)

8150== by 0x921B029: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib64/libQt5Core.so.5.10.0)

8150== by 0x8A798DC: KJob::result(KJob*, KJob::QPrivateSignal) (moc_kjob.cpp:569)

8150== by 0x8A778B4: KJob::finishJob(bool) (kjob.cpp:114)

8150== by 0x8A77F9A: KJob::emitResult() (kjob.cpp:298)

8150== by 0x5F592AB: KIO::SimpleJob::slotFinished() (simplejob.cpp:232)

8150== by 0x5F52050: KIO::ListJob::slotFinished() (listjob.cpp:247)

8150== by 0x5F593C6: KIO::SimpleJob::slotError(int, QString const&) (simplejob.cpp:245)

8150== by 0x5F5BA92: QtPrivate::FunctorCall<QtPrivate::IndexesList<0, 1>, QtPrivate::List<int, QString const&>, void, void (KIO::SimpleJob::*)(int, QString const&)>::call(void (KIO::SimpleJob::*)(int, QString const&), KIO::SimpleJob*, void**) (qobjectdefs_impl.h:136)

8150== by 0x5F5B8EF: void QtPrivate::FunctionPointer<void (KIO::SimpleJob::*)(int, QString const&)>::call<QtPrivate::List<int, QString const&>, void>(void (KIO::SimpleJob::*)(int, QString const&), KIO::SimpleJob*, void**) (qobjectdefs_impl.h:169)

8150== by 0x5F5B65C: QtPrivate::QSlotObject<void (KIO::SimpleJob::*)(int, QString const&), QtPrivate::List<int, QString const&>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:398)

8150== by 0x921B12B: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib64/libQt5Core.so.5.10.0)

8150== by 0x5F3DF91: KIO::SlaveInterface::error(int, QString const&) (moc_slaveinterface.cpp:425)

8150== by 0x5F3BCA5: KIO::SlaveInterface::dispatch(int, QByteArray const&) (slaveinterface.cpp:192)

8150== by 0x5F3B766: KIO::SlaveInterface::dispatch() (slaveinterface.cpp:89)

8150== by 0x5F3FF43: KIO::Slave::gotInput() (slave.cpp:406)

8150== by 0x5FD44FE: KIO::Slave::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (moc_slave.cpp:89)

8150== by 0x921B029: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib64/libQt5Core.so.5.10.0)

8150== by 0x5EE55D4: KIO::Connection::readyRead() (moc_connection_p.cpp:143)

8150== by 0x5EE43C0: KIO::ConnectionPrivate::dequeue() (connection.cpp:46)

8150== by 0x5EE53E5: KIO::Connection::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (moc_connection_p.cpp:87)

When KDialogJobUiDelegate::showErrorMessage() is called, the job is already finished and deleted.

At KIO::SlaveInterface::dispatch(), (slaveinterface.cpp:89) the last data is:
dispatch= 102 data= "\x00\x00\x00\xA3\x00\x00\x00\xC2\x00U\x00n\x00""a\x00""b\x00l\x00""e\x00 \x00t\x00o\x00 \x00""f\x00i\x00n\x00""d\x00 \x00""a\x00n\x00y\x00 \x00w\x00o\x00r\x00k\x00g\x00r\x00o\x00u\x00p\x00s\x00 \x00i\x00n\x00 \x00y\x00o\x00u\x00r\x00 \x00l\x00o\x00""c\x00""a\x00l\x00 \x00n\x00""e\x00t\x00w\x00o\x00r\x00k\x00.\x00 \x00T\x00h\x00i\x00s\x00 \x00m\x00i\x00g\x00h\x00t\x00 \x00""b\x00""e\x00 \x00""c\x00""a\x00u\x00s\x00""e\x00""d\x00 \x00""b\x00y\x00 \x00""a\x00n\x00 \x00""e\x00n\x00""a\x00""b\x00l\x00""e\x00""d\x00 \x00""f\x00i\x00r\x00""e\x00w\x00""a\x00l\x00l\x00."

mpyne added a subscriber: mpyne.Mar 6 2018, 2:31 AM

I'm not sure the job could have been deleted before KDialogJobUiDelegate::showErrorMessage() since much of the call stack before then involves making method calls on the job. KDirLister::handleError(KIO::Job*) (kdirlister.cpp:81) makes a call to job->error() right before calling handleError, for instance.

Is it possible that the widget itself has been deleted early somehow? Does the job run on a different event loop (due to threading or similar)?

I think valgrind has some flags you can use to try to generate a backtrace for where a freed block of memory was freed from, which might be useful for debugging.

dfaure added a comment.Mar 6 2018, 8:38 AM

That's actually valgrind-memcheck's default behaviour.

I think valgrind has some flags you can use to try to generate a backtrace for where a freed block of memory was freed from, which might be useful for debugging.

Thanks. The parameter is --read-var-info=yes, but it confirms my assumption, the job is already deleted and its space used by many others before the crash.
With --tool=helgrind it shows more than 4.500 errors.
With -tool=drd it shows more than 90.000 errors.
Therefore I'll try to fix as many of them as possible, step by step, if it's possible.

dfaure added a comment.Mar 6 2018, 9:56 AM

helgrind and drd are for multithreading data races, but KDirModel can't be used in a multithreading context, so I'm not sure why you're mentioning those tools.

If you do want to detect data races, please note that helgrind and drd have lots of false positives (if you really want to use helgrind, read https://www.kdab.com/~dfaure/helgrind.html), and a much better tool is clang's thread-sanitizer. Downside: you need to build your own Qt first, with -platform linux-clang-libc++ -sanitize thread. Upside: the apps run much faster than with helgrind, and the reports are much more useful.

dfaure requested changes to this revision.Apr 15 2020, 7:55 AM
This revision now requires changes to proceed.Apr 15 2020, 7:55 AM
Restricted Application added a subscriber: kde-frameworks-devel. · View Herald TranscriptApr 15 2020, 7:55 AM