https://bugs.kde.org/show_bug.cgi?id=433402
Bug ID: 433402 Summary: KJobsTest in test suite flags undefined behavior sanitizer Product: frameworks-kcoreaddons Version: 5.79.0 Platform: Compiled Sources OS: Linux Status: REPORTED Severity: minor Priority: NOR Component: general Assignee: mp...@kde.org Reporter: mp...@kde.org CC: kdelibs-b...@kde.org Target Milestone: --- SUMMARY The autotest "kjobtest" causes errors and warning messages about use of undefined behavior. This makes it problematic to run the test suite under aggressive compiler sanitizing because it will then be expected to fail, which reduces the viability of using sanitizers to catch bugs. STEPS TO REPRODUCE 1. Ensure that kcoreaddons is configured to build autotests by CMake. 2. Compile kcoreaddons with Address Sanitizer (asan) and Undefined Behavior Sanitizer (ubsan). I used in my kdesrc-buildrc: options kcoreaddons cmake-options -DBUILD_TESTING:BOOL=ON cxxflags -fsanitize=address -fsanitize=undefined -ggdb end options ***NOTE*** if you do this only for kcoreaddons and install the result, your other Qt/KDE applications may fail to launch. I believe this is due to something about the Qt platform plugin because running something like "XDG_CURRENT_DESKTOP=GNOME assistant" succeeds in this case when just running "assistant" would not. 2. Go to kcoreaddons build directory and run ./bin/kjobtest OBSERVED RESULT user@domain /kdesrc/build/kf5/frameworks/kcoreaddons $ ./bin/kjobtest ********* Start testing of KJobTest ********* Config: Using QtTest library 5.15.1, Qt 5.15.1 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 10.2.0), gentoo unknown PASS : KJobTest::initTestCase() PASS : KJobTest::testEmitResult(no error) PASS : KJobTest::testEmitResult(error no text) PASS : KJobTest::testEmitResult(error with text) PASS : KJobTest::testProgressTracking() PASS : KJobTest::testExec(no error) PASS : KJobTest::testExec(error no text) PASS : KJobTest::testExec(error with text) PASS : KJobTest::testKill(killed with result) PASS : KJobTest::testKill(killed quietly) /kdesrc/src/kf5/frameworks/kcoreaddons/autotests/kjobtest.cpp:439:5: runtime error: downcast of address 0x603000003be0 which does not point to an object of type 'TestJob' 0x603000003be0: note: object is of type 'KJob' 02 00 00 45 b8 a2 71 5f 1c 7f 00 00 20 24 00 00 80 60 00 00 a0 24 00 00 80 60 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'KJob' PASS : KJobTest::testDestroy() PASS : KJobTest::testEmitAtMostOnce(Start-Start-autoDelete) PASS : KJobTest::testEmitAtMostOnce(Start-KillQuietly-autoDelete) PASS : KJobTest::testEmitAtMostOnce(Start-KillVerbosely-autoDelete) PASS : KJobTest::testEmitAtMostOnce(KillQuietly-Start-autoDelete) PASS : KJobTest::testEmitAtMostOnce(KillQuietly-KillQuietly-autoDelete) PASS : KJobTest::testEmitAtMostOnce(KillQuietly-KillVerbosely-autoDelete) PASS : KJobTest::testEmitAtMostOnce(KillVerbosely-Start-autoDelete) PASS : KJobTest::testEmitAtMostOnce(KillVerbosely-KillQuietly-autoDelete) PASS : KJobTest::testEmitAtMostOnce(KillVerbosely-KillVerbosely-autoDelete) PASS : KJobTest::testEmitAtMostOnce(Start-Start) PASS : KJobTest::testEmitAtMostOnce(Start-KillQuietly) PASS : KJobTest::testEmitAtMostOnce(Start-KillVerbosely) PASS : KJobTest::testEmitAtMostOnce(KillQuietly-Start) PASS : KJobTest::testEmitAtMostOnce(KillQuietly-KillQuietly) PASS : KJobTest::testEmitAtMostOnce(KillQuietly-KillVerbosely) PASS : KJobTest::testEmitAtMostOnce(KillVerbosely-Start) PASS : KJobTest::testEmitAtMostOnce(KillVerbosely-KillQuietly) PASS : KJobTest::testEmitAtMostOnce(KillVerbosely-KillVerbosely) PASS : KJobTest::testDelegateUsage() PASS : KJobTest::testNestedExec() PASS : KJobTest::cleanupTestCase() Totals: 32 passed, 0 failed, 0 skipped, 0 blacklisted, 302ms ********* Finished testing of KJobTest ********* ================================================================= ==131922==ERROR: LeakSanitizer: detected memory leaks Direct leak of 16 byte(s) in 2 object(s) allocated from: #0 0x7f1c60269b48 in __interceptor_realloc /var/tmp/portage/sys-devel/gcc-10.2.0-r5/work/gcc-10.2.0/libsanitizer/asan/asan_malloc_linux.cpp:164 #1 0x7f1c5e0d5f42 in d_growable_string_resize /var/tmp/portage/sys-devel/gcc-10.2.0-r5/work/build/x86_64-pc-linux-gnu/libstdc++-v3/libsupc++/cp-demangle.c:4036 #2 0x7f1c5e0d5f42 in d_growable_string_append_buffer /var/tmp/portage/sys-devel/gcc-10.2.0-r5/work/build/x86_64-pc-linux-gnu/libstdc++-v3/libsupc++/cp-demangle.c:4060 #3 0x7f1c5e0d5f42 in d_growable_string_callback_adapter /var/tmp/portage/sys-devel/gcc-10.2.0-r5/work/build/x86_64-pc-linux-gnu/libstdc++-v3/libsupc++/cp-demangle.c:4077 SUMMARY: AddressSanitizer: 16 byte(s) leaked in 2 allocation(s). EXPECTED RESULT I expected a result as above but without warnings from the compiler about a downcast to an improper type. SOFTWARE/OS VERSIONS Linux/KDE Plasma: Gentoo Linux 5.11.0-rc7-00115-gc6d8570e4d64 (64-bit) on X11 KDE Plasma Version: 5.21.80 KDE Frameworks Version: 5.80.0 Qt Version: 5.15.1 ADDITIONAL INFORMATION The test case admits the undefined behavior going on (in KJobTest::slotFinished): // qobject_cast and dynamic_cast to TestJob* fail when finished() signal is emitted from // ~KJob(). The static_cast allows to call the otherwise protected KJob::isFinished(). // WARNING: don't use this trick in production code, because static_cast-ing // to a wrong type and then dereferencing the pointer is undefined behavior. // Normally a KJob and its subclasses should manage their finished state on their own. // If you *really* need KJob::isFinished() to be public, request this access // modifier change in the KJob class. QVERIFY(static_cast<const TestJob *>(job)->isFinished()); slotFinished isn't always called from the KJob destructor in this test case but it is at least once. However if you look at the KJob API for KJob::isFinished() [1] it is clear that this function is only helpful to KJob itself, not to external classes or any subclasses, in the context of being checked from the KJob destructor. Since the method is protected it can only be called by KJob or subclasses, but by the time KJob::~KJob() runs, there are no more subclasses to use it. So I'm not sure that there is value in double-checking that KJob::isFinished() operates successfully in the narrow use case of KJob::~KJob(). [1] https://api.kde.org/frameworks/kcoreaddons/html/classKJob.html#a67b6c63fc5eb7bd31234960e7a5487d9 -- You are receiving this mail because: You are watching all bug changes.