lxqt / pcmanfm-qt

File manager and desktop icon manager (Qt port of PCManFM and libfm)
https://lxqt-project.org
GNU General Public License v2.0
413 stars 113 forks source link

Size limit for thumbnail creation has no effect #1315

Closed The-Compiler closed 3 years ago

The-Compiler commented 3 years ago
Expected Behavior

Showing a thumbnail for an invalid image file should be handled gracefully in some way.

Current Behavior

pcmanfm-qt crashes with:

Qt Concurrent has caught an exception thrown from a worker thread.
This is not supported, exceptions thrown in worker threads must be
caught before control returns to Qt Concurrent.
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Steps to Reproduce (for bugs)
  1. Download the following files: buggy.zip
  2. Run gcc -o a3buggy a3buggy.c bmp.c
  3. Ensure you're on a file system like ext4, which does not actually allocate long blocks of null-bytes on disk (or the next step will likely fill your entire filesystem).
  4. Run ./a3buggy which generates an a3.bmp. Its file size shows as 1.6 TB on my system, yet most of it are null-bytes. (This also is the reason why I'm not uploading the file directly - I couldn't find a way to do so!)
Context

I'm teaching an university course where we have various exercises (to explain concepts like multithreading, etc.) based on generating fractal images. A student ended up writing the given a3buggy.c (with SIZE-y instead of SIZE-1-y), which together with bmp.c (written by someone before I took over...) seems to generate something very strange.

Their pcmanfm-qt in an Ubuntu VM crashed. I've tried to reproduce locally on Archlinux, and I can indeed reproduce it. I don't know what's up with the generated BMP exactly, but given that it isn't actually as big as it seems to be, I feel like it should be handled gracefully in some way.

System Information
tsujan commented 3 years ago

There's something very odd with this file, and I haven't been able to figure out what's going on with it. Its file size shows as 1.6 TB on my system,

So, I'll never test it.

When a crash happens, a backtrace is needed. Please attach a standard backtrace to your report for it to be investigated.

I've never seen pcmanfm-qt crashing because of thumbnail creation and I don't think that's possible but will check the code again.

The-Compiler commented 3 years ago

The crash is due to an abort() from Qt, see above. I didn't attach a stacktrace because it really isn't useful, but here you go:

#0  0x00007ffff6419ef5 in raise () at /usr/lib/libc.so.6
#1  0x00007ffff6403862 in abort () at /usr/lib/libc.so.6
#2  0x00007ffff664086a in __gnu_cxx::__verbose_terminate_handler() () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007ffff664cd3a in __cxxabiv1::__terminate(void (*)()) (handler=<optimized out>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:48
#4  0x00007ffff664cda7 in std::terminate() () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:58
#5  0x00007ffff6b8bcff in qt_assert(char const*, char const*, int) () at /usr/lib/libQt5Core.so.5
#6  0x00007ffff6b8d864 in  () at /usr/lib/libQt5Core.so.5
#7  0x00007ffff63c3299 in start_thread () at /usr/lib/libpthread.so.0
#8  0x00007ffff64dc053 in clone () at /usr/lib/libc.so.6
tsujan commented 3 years ago

@The-Compiler That's not a backtrace. Please consult the documentation of your distro on how getting backtraces.

The-Compiler commented 3 years ago

Can you elaborate on what makes you think so? That's the output of bt after running pcmanfm-qt in gdb. Here is the full output:

``` $ gdb /usr/bin/pcmanfm-qt GNU gdb (GDB) 10.1 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /usr/bin/pcmanfm-qt... (No debugging symbols found in /usr/bin/pcmanfm-qt) (gdb) r Starting program: /usr/bin/pcmanfm-qt [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib/libthread_db.so.1". (gdb) [New Thread 0x7ffff314d640 (LWP 339728)] [New Thread 0x7ffff1d71640 (LWP 339729)] isPrimaryInstance [New Thread 0x7ffff1570640 (LWP 339730)] [New Thread 0x7ffff0d6f640 (LWP 339731)] [Thread 0x7ffff1570640 (LWP 339730) exited] [New Thread 0x7ffff1570640 (LWP 339732)] [New Thread 0x7fffe377d640 (LWP 339733)] [New Thread 0x7fffe2f7c640 (LWP 339734)] [New Thread 0x7fffe0bda640 (LWP 339735)] [New Thread 0x7fffca5a0640 (LWP 339736)] [New Thread 0x7fffc9d9f640 (LWP 339737)] [New Thread 0x7fffc959e640 (LWP 339738)] [New Thread 0x7fffc8d9d640 (LWP 339739)] [New Thread 0x7fffbbfff640 (LWP 339740)] [New Thread 0x7fffbb7fe640 (LWP 339741)] [New Thread 0x7fffbaffd640 (LWP 339742)] [New Thread 0x7fffba7fc640 (LWP 339743)] [New Thread 0x7fffb9ffb640 (LWP 339744)] [New Thread 0x7fffb97fa640 (LWP 339745)] [New Thread 0x7fffb8ff9640 (LWP 339746)] [New Thread 0x7fff97fff640 (LWP 339747)] [New Thread 0x7fff977fe640 (LWP 339748)] [New Thread 0x7fff96ffd640 (LWP 339749)] [New Thread 0x7fff967fc640 (LWP 339750)] [New Thread 0x7fff95ffb640 (LWP 339751)] [New Thread 0x7fff957fa640 (LWP 339752)] [New Thread 0x7fff94ff9640 (LWP 339753)] [New Thread 0x7fff7ffff640 (LWP 339754)] [New Thread 0x7fff7f7fe640 (LWP 339755)] [New Thread 0x7fff7effd640 (LWP 339756)] [Thread 0x7fffe2f7c640 (LWP 339734) exited] [Thread 0x7ffff1570640 (LWP 339732) exited] [New Thread 0x7fffe2f7c640 (LWP 339757)] [Thread 0x7fffe377d640 (LWP 339733) exited] [New Thread 0x7fffe377d640 (LWP 339760)] [Thread 0x7fffe2f7c640 (LWP 339757) exited] [New Thread 0x7fffe2f7c640 (LWP 339761)] [Thread 0x7fffe377d640 (LWP 339760) exited] [New Thread 0x7fffe377d640 (LWP 339762)] [Thread 0x7fffe2f7c640 (LWP 339761) exited] Qt Concurrent has caught an exception thrown from a worker thread. This is not supported, exceptions thrown in worker threads must be caught before control returns to Qt Concurrent. terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Thread 34 "Thread (pooled)" received signal SIGABRT, Aborted. [Switching to Thread 0x7fffe377d640 (LWP 339762)] --Type for more, q to quit, c to continue without paging-- 0x00007ffff6419ef5 in raise () from /usr/lib/libc.so.6 (gdb) bt #0 0x00007ffff6419ef5 in raise () at /usr/lib/libc.so.6 #1 0x00007ffff6403862 in abort () at /usr/lib/libc.so.6 #2 0x00007ffff664086a in __gnu_cxx::__verbose_terminate_handler() () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/vterminate.cc:95 #3 0x00007ffff664cd3a in __cxxabiv1::__terminate(void (*)()) (handler=) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:48 #4 0x00007ffff664cda7 in std::terminate() () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:58 #5 0x00007ffff6b8bcff in qt_assert(char const*, char const*, int) () at /usr/lib/libQt5Core.so.5 #6 0x00007ffff6b8d864 in () at /usr/lib/libQt5Core.so.5 #7 0x00007ffff63c3299 in start_thread () at /usr/lib/libpthread.so.0 #8 0x00007ffff64dc053 in clone () at /usr/lib/libc.so.6 ```

As for the file size, I edited by post above shortly after creating it, but looks like we had a race condition :wink:. The file does actually seem to contain 1.5 TB of NULL-bytes, but ext4 does not actually allocate those, which is why it's quick to create (and doesn't actually use any disk space).

tsujan commented 3 years ago

Can you elaborate on what makes you think so?

Because there wasn't any trace of libfm-qt or pcmanfm-qt in it; otherwise, you're right, it was a backtrace.

Closing because of that but the report could be reopened if a real evidence is provided for libfm-qt's role in this crash (which seems like a crash in Qt).

The-Compiler commented 3 years ago

Those are not in the backtrace because Qt catches all unhandled exceptions from worker threads and then displays this message, thus hiding the original backtrace.

I managed to get it by setting a catchpoint via catch throw bad_alloc:

#0  0x00007ffff664d012 in __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*)) (obj=0x7fffe8009710, tinfo=0x7ffff6777ee0 <typeinfo for std::bad_alloc>, dest=0x7ffff664b2e0 <std::bad_alloc::~bad_alloc()>)
    at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:78
#1  0x00007ffff6640438 in operator new(unsigned long) (sz=1649267441718) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
#2  0x00007ffff7e446dd in Fm::ThumbnailJob::readImageFromStream(_GInputStream*, unsigned long) () at /usr/lib/libfm-qt.so.8
#3  0x00007ffff7e45276 in Fm::ThumbnailJob::generateThumbnail(std::shared_ptr<Fm::FileInfo const> const&, Fm::FilePath const&, char const*, QString const&) () at /usr/lib/libfm-qt.so.8
#4  0x00007ffff7e45a5d in Fm::ThumbnailJob::loadForFile(std::shared_ptr<Fm::FileInfo const> const&) () at /usr/lib/libfm-qt.so.8
#5  0x00007ffff7e45e1c in Fm::ThumbnailJob::exec() () at /usr/lib/libfm-qt.so.8
#6  0x00007ffff7e3c94f in non-virtual thunk to Fm::Job::run() () at /usr/lib/libfm-qt.so.8
#7  0x00007ffff6bcd2f2 in  () at /usr/lib/libQt5Core.so.5
#8  0x00007ffff6bc9eff in  () at /usr/lib/libQt5Core.so.5
#9  0x00007ffff63c3299 in start_thread () at /usr/lib/libpthread.so.0
#10 0x00007ffff64dc053 in clone () at /usr/lib/libc.so.6

and sure enough, the relevant code says:

QImage ThumbnailJob::readImageFromStream(GInputStream* stream, size_t len) {
    // FIXME: should we set a limit here? Otherwise if len is too large, we can run out of memory.
    std::unique_ptr<unsigned char[]> buffer{new unsigned char[len]}; // allocate enough buffer
tsujan commented 3 years ago

Thanks! Reopening because the new backtrace shows a problem in libfm-qt.

tsujan commented 3 years ago

The fix is here: https://github.com/lxqt/libfm-qt/pull/634. Apparently, the size limit was forgotten during the heavy C++11 port of libfm-qt, a long time ago, but no one had noticed that.

Thanks for reporting!