Skip to content

Double-free in ~LogMsg #2372

@xsdg

Description

@xsdg

Setup (please complete the following information):

  • Geeqie version [geeqie --version]: Geeqie 2.7+git20260525-55b54b58 GTK3

Spotted by ASAN after a crash. It's possible that this is related to multiple LogMsg instances being created with the same gchar* -- but as far as I can tell, std::string(const char*) should always make a copy. Otherwise, this may be related to the struct not following the rule of 3/5/0. Either way, it looks like both thread T0 and T14 are trying to run the destructor for the same LogMsg instance, which results in the double-free.

Code snippet:

struct LogMsg {
        LogMsg() = default;
        LogMsg(const gchar *text, LogType type)
                : text(text)
                , type(type)
        {}
        std::string text;
	LogType type;
};
==750327==ERROR: AddressSanitizer: attempting double-free on 0x7baca2e06c90 in thread T14:
    #0 0x7f7ca5f1bb1b in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:155
    #1 0x55dbabe2cab5 in std::__new_allocator<char>::deallocate(char*, unsigned long) /usr/include/c++/15/bits/new_allocator.h:172
    #2 0x55dbabe2cab5 in std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long) /usr/include/c++/15/bits/alloc_traits.h:649
    #3 0x55dbabe2cab5 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_destroy(unsigned long) /usr/include/c++/15/bits/basic_string.h:305
    #4 0x55dbabe2cab5 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose() /usr/include/c++/15/bits/basic_string.h:299
    #5 0x55dbabf6c51f in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() /usr/include/c++/15/bits/basic_string.h:896
    #6 0x55dbabf6c51f in LogMsg::~LogMsg() ../src/logwindow.cc:498
    #7 0x55dbabf6c51f in void std::_Destroy<LogMsg>(LogMsg*) /usr/include/c++/15/bits/stl_construct.h:166
    #8 0x55dbabf6c51f in void std::_Destroy<LogMsg*>(LogMsg*, LogMsg*) /usr/include/c++/15/bits/stl_construct.h:226
    #9 0x55dbabf6c51f in void std::_Destroy<LogMsg*, LogMsg>(LogMsg*, LogMsg*, std::allocator<LogMsg>&) /usr/include/c++/15/bits/alloc_traits.h:1045
    #10 0x55dbabf6c51f in std::deque<LogMsg, std::allocator<LogMsg> >::_M_destroy_data_aux(std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>, std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>) /usr/include/c++/15/bits/deque.tcc:1041
    #11 0x55dbabf6c7d9 in std::deque<LogMsg, std::allocator<LogMsg> >::_M_destroy_data(std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>, std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>, std::allocator<LogMsg> const&) /usr/include/c++/15/bits/stl_deque.h:2204
    #12 0x55dbabf6cb21 in std::deque<LogMsg, std::allocator<LogMsg> >::~deque() /usr/include/c++/15/bits/stl_deque.h:1043
    #13 0x7f7ca424b3a0 in __run_exit_handlers stdlib/exit.c:118
    #14 0x7f7ca424b46b in __GI_exit stdlib/exit.c:148
    #15 0x55dbabf71df4 in sig_handler_cb ../src/main.cc:274
    #16 0x7f7ca4248e2f  (/usr/lib/x86_64-linux-gnu/libc.so.6+0x40e2f) (BuildId: e0715e6b2fc508102cc2100d3d25a1aa4eb676f9)
    #17 0x7f7ca508beb8 in jpeg_fill_bit_buffer src/jdhuff.c:310
    #18 0x7f7ca509b71b in decode_mcu_DC_first src/jdphuff.c:329
    #19 0x7f7ca507f4c6 in consume_data src/wrapper/../jdcoefct.c:236
    #20 0x7f7ca507af80 in jpeg_start_decompress src/wrapper/../jdapistd.c:74
    #21 0x55dbac072253 in ImageLoaderJpeg::write(unsigned char const*, unsigned long&, unsigned long, _GError**) ../src/image-load-jpeg.cc:360
    #22 0x55dbabf12b0f in image_loader_begin ../src/image-load.cc:858
    #23 0x55dbabf13214 in image_loader_thread_run ../src/image-load.cc:1151
    #24 0x7f7ca51f2e29  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x92e29) (BuildId: fa948a74679999d95c17c8bbbcc0dfd3752f17aa)
    #25 0x7f7ca51f2675  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x92675) (BuildId: fa948a74679999d95c17c8bbbcc0dfd3752f17aa)
    #26 0x7f7ca5e5c0f5 in asan_thread_start ../../../../src/libsanitizer/asan/asan_interceptors.cpp:239
    #27 0x7f7ca429dda8 in start_thread nptl/pthread_create.c:448
    #28 0x7f7ca431ce07 in __clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

0x7baca2e06c90 is located 0 bytes inside of 28-byte region [0x7baca2e06c90,0x7baca2e06cac)
freed by thread T0 here:
    #0 0x7f7ca5f1bb1b in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:155
    #1 0x55dbabe2cab5 in std::__new_allocator<char>::deallocate(char*, unsigned long) /usr/include/c++/15/bits/new_allocator.h:172
    #2 0x55dbabe2cab5 in std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long) /usr/include/c++/15/bits/alloc_traits.h:649
    #3 0x55dbabe2cab5 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_destroy(unsigned long) /usr/include/c++/15/bits/basic_string.h:305
    #4 0x55dbabe2cab5 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose() /usr/include/c++/15/bits/basic_string.h:299
    #5 0x55dbabf6c577 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() /usr/include/c++/15/bits/basic_string.h:896
    #6 0x55dbabf6c577 in LogMsg::~LogMsg() ../src/logwindow.cc:498
    #7 0x55dbabf6c577 in void std::_Destroy<LogMsg>(LogMsg*) /usr/include/c++/15/bits/stl_construct.h:166
    #8 0x55dbabf6c577 in void std::_Destroy<LogMsg*>(LogMsg*, LogMsg*) /usr/include/c++/15/bits/stl_construct.h:226
    #9 0x55dbabf6c577 in void std::_Destroy<LogMsg*, LogMsg>(LogMsg*, LogMsg*, std::allocator<LogMsg>&) /usr/include/c++/15/bits/alloc_traits.h:1045
    #10 0x55dbabf6c577 in std::deque<LogMsg, std::allocator<LogMsg> >::_M_destroy_data_aux(std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>, std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>) /usr/include/c++/15/bits/deque.tcc:1045
    #11 0x55dbabf6c7d9 in std::deque<LogMsg, std::allocator<LogMsg> >::_M_destroy_data(std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>, std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>, std::allocator<LogMsg> const&) /usr/include/c++/15/bits/stl_deque.h:2204
    #12 0x55dbabf6ce7d in std::deque<LogMsg, std::allocator<LogMsg> >::_M_erase_at_end(std::_Deque_iterator<LogMsg, LogMsg&, LogMsg*>) /usr/include/c++/15/bits/stl_deque.h:2221
    #13 0x55dbabf6feb7 in std::deque<LogMsg, std::allocator<LogMsg> >::resize(unsigned long) /usr/include/c++/15/bits/stl_deque.h:1361
    #14 0x55dbabf6afa6 in log_window_append(char const*, LogType) ../src/logwindow.cc:534
    #15 0x55dbabe80e84 in log_normal_cb ../src/debug.cc:84
    #16 0x7f7ca51bc68d  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5c68d) (BuildId: fa948a74679999d95c17c8bbbcc0dfd3752f17aa)

previously allocated by thread T0 here:
    #0 0x7f7ca5f1abbb in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:86
    #1 0x55dbabe2cb1b in std::__new_allocator<char>::allocate(unsigned long, void const*) /usr/include/c++/15/bits/new_allocator.h:151
    #2 0x55dbabe2cb1b in std::allocator_traits<std::allocator<char> >::allocate(std::allocator<char>&, unsigned long) /usr/include/c++/15/bits/alloc_traits.h:614
    #3 0x55dbabe2cb1b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_allocate(std::allocator<char>&, unsigned long) /usr/include/c++/15/bits/basic_string.h:142
    #4 0x55dbabe2cb1b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long) /usr/include/c++/15/bits/basic_string.tcc:164
    #5 0x55dbabe2f9e7 in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) /usr/include/c++/15/bits/basic_string.tcc:235
    #6 0x55dbabe2fc21 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&) /usr/include/c++/15/bits/basic_string.h:714
    #7 0x55dbabf6f3f0 in LogMsg::LogMsg(char const*, LogType) ../src/logwindow.cc:501
    #8 0x55dbabf6f3f0 in void std::__new_allocator<LogMsg>::construct<LogMsg, char const*&, LogType&>(LogMsg*, char const*&, LogType&) /usr/include/c++/15/bits/new_allocator.h:191
    #9 0x55dbabf6f3f0 in void std::allocator_traits<std::allocator<LogMsg> >::construct<LogMsg, char const*&, LogType&>(std::allocator<LogMsg>&, LogMsg*, char const*&, LogType&) /usr/include/c++/15/bits/alloc_traits.h:674
    #10 0x55dbabf6f3f0 in LogMsg& std::deque<LogMsg, std::allocator<LogMsg> >::emplace_front<char const*&, LogType&>(char const*&, LogType&) /usr/include/c++/15/bits/deque.tcc:145
    #11 0x55dbabf6af0f in log_window_append(char const*, LogType) ../src/logwindow.cc:528
    #12 0x55dbabe80dbe in log_msg_cb ../src/debug.cc:54
    #13 0x7f7ca51bc68d  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5c68d) (BuildId: fa948a74679999d95c17c8bbbcc0dfd3752f17aa)

Thread T14 created by T2 here:
    #0 0x7f7ca5f11612 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:250
    #1 0x7f7ca51f11c8  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x911c8) (BuildId: fa948a74679999d95c17c8bbbcc0dfd3752f17aa)

Thread T2 created by T0 here:
    #0 0x7f7ca5f11612 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:250
    #1 0x7f7ca51f11c8  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x911c8) (BuildId: fa948a74679999d95c17c8bbbcc0dfd3752f17aa)

SUMMARY: AddressSanitizer: double-free ../src/logwindow.cc:498 in LogMsg::~LogMsg()

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions