Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.41.0: Crash on double free #1200

Closed
mozbugbox opened this issue Jan 22, 2023 · 7 comments
Closed

1.41.0: Crash on double free #1200

mozbugbox opened this issue Jan 22, 2023 · 7 comments
Assignees
Labels
Milestone

Comments

@mozbugbox
Copy link
Contributor

mozbugbox commented Jan 22, 2023

Liferea 1.41.0 crash randomly.

 "double free or corruption (fasttop)"
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0)
    at ./nptl/pthread_kill.c:44
        tid = <optimized out>
        ret = 0
        pd = <optimized out>
        old_mask = {__val = {261}}
        ret = <optimized out>
#1  0x00007fd7a5810d2f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  0x00007fd7a57c1ef2 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
        ret = <optimized out>
#3  0x00007fd7a57ac472 in __GI_abort () at ./stdlib/abort.c:79
        save_stage = 1
        act = 
          {__sigaction_handler = {sa_handler = 0x20, sa_sigaction = 0x20}, sa_mask = {__val = {64, 140734351281424, 1, 94145683128581, 140564182806405, 94149163161600, 94149182439824, 94149206566544, 140564173990921, 94149163161600, 140564173985546, 94149206566544, 94149142946832, 94149163161600, 94149142946832, 0}}, sa_flags = -1514672848, sa_restorer = 0x55a0d20db9d0}
#4  0x00007fd7a58052d0 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fd7a591f459 "%s\n")
    at ../sysdeps/posix/libc_fatal.c:155
        ap = {{gp_offset = 24, fp_offset = 32767, overflow_arg_area = 0x7fff45040f30, reg_save_area = 0x7fff45040ec0}}
        fd = <optimized out>
        list = <optimized out>
        nlist = <optimized out>
        cp = <optimized out>
#5  0x00007fd7a581a64a in malloc_printerr (str=str@entry=0x7fd7a59220d0 "double free or corruption (fasttop)")
    at ./malloc/malloc.c:5660
#6  0x00007fd7a581c362 in _int_free (av=0x7fd7a5958c60 <main_arena>, p=0x55a0cf7ccb10, have_lock=have_lock@entry=0)
    at ./malloc/malloc.c:4535
        idx = 3
        old = <optimized out>
        old2 = <optimized out>
        size = <optimized out>
        fb = 0x7fd7a5958c88 <main_arena+40>
        nextchunk = <optimized out>
        nextsize = <optimized out>
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        __PRETTY_FUNCTION__ = "_int_free"
#7  0x00007fd7a581ed2f in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3385
        ar_ptr = <optimized out>
        p = <optimized out>
        err = 11
#8  0x000055a0ce34bb8d in item_unload (item=0x55a0d204c890) at ../item.c:216
        __func__ = "item_unload"
#9  0x000055a0ce34e528 in itemlist_check_for_deferred_action () at ../itemlist.c:242
        item = <optimized out>
#10 0x000055a0ce34e955 in itemlist_check_for_deferred_action () at ../itemlist.c:180
        __PRETTY_FUNCTION__ = "itemlist_selection_changed"
#11 itemlist_selection_changed (item=item@entry=0x55a0d204c7d0) at ../itemlist.c:562
        __PRETTY_FUNCTION__ = "itemlist_selection_changed"
#12 0x000055a0ce37c416 in on_itemlist_selection_changed (selection=<optimized out>, user_data=<optimized out>) at ./src/ui/item_list_view.c:316
        id = <optimized out>
        iter = {stamp = 1249431851, user_data = 0x55a0d1931730, user_data2 = 0x0, user_data3 = 0x0}
        model = 0x55a0d1485f80
        item = 0x55a0d204c7d0
#13 0x00007fd7a5b965a9 in  () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#14 0x00007fd7a5bafbbf in g_signal_emit_valist () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#15 0x00007fd7a5bafdbf in g_signal_emit () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#16 0x00007fd7a63169a4 in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#17 0x000055a0ce37d6a6 in item_list_view_select (ilv=<optimized out>, item=item@entry=0x55a0d204d7e0) at ./src/ui/item_list_view.c:1063
        path = 0x55a0d2592900
        treeview = 0x55a0cfa9e7c0
        selection = 0x55a0d0301c80
        iter = {stamp = 1249431851, user_data = 0x55a0d1931730, user_data2 = 0x0, user_data3 = 0x0}
#18 0x000055a0ce36e09a in itemview_select_item (item=0x55a0d204d7e0) at ./src/ui/itemview.c:198
#19 0x000055a0ce34e34c in itemlist_select_next_unread () at ../itemlist.c:412
        result = <optimized out>
#20 0x000055a0ce37d815 in on_next_unread_item_activate (menuitem=<optimized out>, parameter=<optimized out>, user_data=<optimized out>) at ./src/ui/item_list_view.c:1105
#21 0x000055a0ce38182b in scroll_pagedown_callback (source_object=0x55a0cf5c0600, res=0x55a0cf841980, user_data=<optimized out>) at ./src/webkit/liferea_web_view.c:715
        result = <optimized out>
        error = 0x0
        scrolled = 0
#22 0x00007fd7a5ce1c93 in  () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#23 0x00007fd7a5ce2673 in  () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#24 0x00007fd7a5d3ba12 in  () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#25 0x00007fd7a5ce1c93 in  () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#26 0x00007fd7a5ce1cc9 in  () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#27 0x00007fd7a5a9c67f in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#28 0x00007fd7a5a9ca38 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#29 0x00007fd7a5a9cacc in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#30 0x00007fd7a5d0f65d in g_application_run () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#31 0x000055a0ce34f710 in liferea_application_new (argc=1, argv=0x7fff45041788) at ../liferea_application.c:354
        status = <optimized out>
        __func__ = "liferea_application_new"
#32 0x00007fd7a57ad18a in __libc_start_call_main (main=main@entry=0x55a0ce33e780 <main>, argc=argc@entry=1, argv=argv@entry=0x7fff45041788) at ../sysdeps/nptl/libc_start_call_main.h:58
        self = <optimized out>
        result = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140734351284104, 4823506045173161346, 0, 140734351284120, 94149143107408, 140564281438240, -4823914607393579646, -4800903428874642046}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x7fff45041788, 0x7fff45041788}, data = {prev = 0x0, cleanup = 0x0, canceltype = 1157896072}}}
        not_first_call = <optimized out>
#33 0x00007fd7a57ad245 in __libc_start_main_impl (main=0x55a0ce33e780 <main>, argc=1, argv=0x7fff45041788, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff45041778) at ../csu/libc-start.c:381
#34 0x000055a0ce33e821 in _start ()
quit
@lwindolf lwindolf added the bug label Jan 24, 2023
@lwindolf lwindolf added this to the 1.14.1 milestone Jan 24, 2023
@lwindolf
Copy link
Owner

Must be a bug in the recent refactoring in on_itemlist_selection_changed

@mozbugbox
Copy link
Contributor Author

From the look at it, it seems that in the following code, the itemlist_remove_item (item); will unload the item. If that line was called, then the following item_unload(item); would cause a double free on the item.

I don't know when the itemlist->priv->deferredRemove will be TRUE, though. I did not do any search folder thing every time when it crashed.

liferea/src/itemlist.c

Lines 235 to 244 in c6ee722

/* check for item unloading caused by search folder rules (i.e. unread items only) */
if (itemlist->priv->deferredRemove) {
itemlist->priv->deferredRemove = FALSE;
itemlist_remove_item (item);
}
item_unload (item);
}

@mozbugbox
Copy link
Contributor Author

Actually, by implicitly free the item inside the itemlist_remove_item() call, it could also cause double free at:

liferea/src/itemlist.c

Lines 500 to 514 in c6ee722

while (iter) {
itemPtr item = (itemPtr) iter->data;
if (itemlist->priv->selectedId != item->id) {
/* don't call itemlist_remove_item() here, because it's to slow */
itemview_remove_item (item);
db_item_remove (item->id);
} else {
/* go the normal and selection-safe way to avoid disturbing the user */
itemlist_request_remove_item (item);
}
item_unload (item);
iter = g_list_next (iter);
}

as itemlist_request_remove_item() will call itemlist_remove_item() on item.

@lwindolf
Copy link
Owner

lwindolf commented Feb 4, 2023

@mozbugbox Can you please retest? I've converted the item implementation to GObject to allow for keeping more than one reference (should it become necessary) and fixed the 2 cases you've outlined above.

Thanks for analyzing this!

@lwindolf lwindolf self-assigned this Feb 4, 2023
@mozbugbox
Copy link
Contributor Author

@mozbugbox Can you please retest? I've converted the item implementation to
GObject to allow for keeping more than one reference (should it become
necessary) and fixed the 2 cases you've outlined above.

Really glade that the item was converted to a GObject. Now it can be
included in the gobject-introspect. When doing plugin, quite a few features require to access item value, i.e. item->source.

@mozbugbox
Copy link
Contributor Author

I got another crash now at about the same place but is a different one.

#0  0x000055e8553e2e81 in itemlist_remove_item (item=0x0) at ../../../../src/tests/../itemlist.c:464
#1  0x000055e8553e2722 in itemlist_check_for_deferred_action () at ../../../../src/tests/../itemlist.c:244
        item = 0x0
        keep_for_search_folder = 1
#2  0x000055e8553e3194 in itemlist_selection_changed (item=0x55e858a3b160) at ../../../../src/tests/../itemlist.c:560
        __PRETTY_FUNCTION__ = "itemlist_selection_changed"
#3  0x000055e85541c60f in on_itemlist_selection_changed (selection=0x55e8563aa880, user_data=0x55e8563aa800)
    at ../../../../src/ui/item_list_view.c:316
        id = 17403386
        iter = {stamp = 1210205116, user_data = 0x55e857157720, user_data2 = 0x0, user_data3 = 0x0}
        model = 0x55e857455cf0
        item = 0x55e858a3b160
#4  0x00007f1f065b15a9 in  () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#5  0x00007f1f065cabbf in g_signal_emit_valist () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#6  0x00007f1f065cadbf in g_signal_emit () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#7  0x00007f1f06d319a4 in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#8  0x00007f1f06d3ab32 in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#9  0x00007f1f06a79f09 in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#10 0x00007f1f065b15a9 in  () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#11 0x00007f1f065cabbf in g_signal_emit_valist () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#12 0x00007f1f065cadbf in g_signal_emit () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#13 0x00007f1f06b9d10f in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#14 0x00007f1f065b4362 in g_cclosure_marshal_VOID__BOXEDv () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#15 0x00007f1f065b15a9 in  () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#16 0x00007f1f065cabbf in g_signal_emit_valist () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#17 0x00007f1f065cadbf in g_signal_emit () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#18 0x00007f1f06b9993e in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#19 0x00007f1f06b9af9a in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#20 0x00007f1f06b9e65e in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#21 0x00007f1f06b5e091 in gtk_event_controller_handle_event () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#22 0x00007f1f06d4a98d in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#23 0x00007f1f06a73bb7 in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#24 0x00007f1f065b13b0 in g_closure_invoke () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#25 0x00007f1f065c41a5 in  () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#26 0x00007f1f065ca42d in g_signal_emit_valist () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#27 0x00007f1f065cadbf in g_signal_emit () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#28 0x00007f1f06d4c4f4 in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#29 0x00007f1f06bea7ee in  () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#30 0x00007f1f06bec2a6 in gtk_main_do_event () at /lib/x86_64-linux-gnu/libgtk-3.so.0
#31 0x00007f1f06916815 in  () at /lib/x86_64-linux-gnu/libgdk-3.so.0
#32 0x00007f1f06970412 in  () at /lib/x86_64-linux-gnu/libgdk-3.so.0
#33 0x00007f1f064b77a9 in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#34 0x00007f1f064b7a38 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#35 0x00007f1f064b7acc in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#36 0x00007f1f0672a65d in g_application_run () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#37 0x000055e8553e4601 in liferea_application_new (argc=1, argv=0x7ffd4b3d1818) at ../../../../src/tests/../liferea_application.c:354
        status = 0
        __func__ = "liferea_application_new"
#38 0x000055e8553f0513 in main (argc=1, argv=0x7ffd4b3d1818) at ../../../src/main.c:61
quit

As can be see the item in itemlist_check_for_deferred_action () was actually 0x0 now.

It seems that the itemlist selected_id was not reset correctly, as a result, the check for selected_id was TRUE while itemlist_get_selected () returns NULL.

liferea/src/itemlist.c

Lines 213 to 222 in e1d0915

itemlist_check_for_deferred_action (void)
{
itemPtr item;
if (!itemlist_get_selected_id ())
return;
item = itemlist_get_selected ();
itemlist_set_selected (NULL);

@mozbugbox
Copy link
Contributor Author

I can reliably reproduce the crash by the following code

import random
print("""\
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Random 360 Atom Feed</title>
""")
for i in range(360):
    r = random.randint(100000, 999999)
    eid = f"{i}{r}"
    print(f"""\
    <entry>
        <title>{i}-{r} An Entry</title>
        <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-{eid}</id>
        <link href="http://example.org/atom{eid}" />
    </entry>
""")
print("</feed>")
  1. subscribe the code as command source.
  2. select one item in the feed
  3. update the feed again
  4. try to select an item in the feed
  5. crash

It's like old selected item was removed without reset the selected_id field of itemlist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants