Crash on DnD with gtk notebook tabs gtk-4.18.5

Everything was working fine until I updated my Archlinux box to gtk-4.18.5 and then, DnD from gtk.gridview items in a notebook with multiple tabs has gone crazy, leading to crash.

I followed the issue with valgrind and it seems there is a memory corruption, at least, with an invalid write. You can see the valgrind output below. If you wish to reproduce, get the code from GitHub - edscott/xffm, change dir to gtk4,
mkdir build, change dir to build, cmake …, and finally make.
Then just start opening tabs and dragging icons from there to gvim and between tabs.

==3712778== Memcheck, a memory error detector
==3712778== Copyright (C) 2002-2024, and GNU GPL’d, by Julian Seward et al.
==3712778== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==3712778== Command: xffm4
==3712778==
INFO> User set terminal = xterm -vb -rv
==3734732==
==3734732== HEAP SUMMARY:
==3734732== in use at exit: 45,456,944 bytes in 245,698 blocks
==3734732== total heap usage: 1,780,398 allocs, 1,534,700 frees, 948,682,561 bytes allocated
==3734732==
==3734732== LEAK SUMMARY:
==3734732== definitely lost: 30,618 bytes in 2,407 blocks
==3734732== indirectly lost: 451,285 bytes in 5,812 blocks
==3734732== possibly lost: 4,210,471 bytes in 26,700 blocks
==3734732== still reachable: 39,358,962 bytes in 201,625 blocks
==3734732== of which reachable via heuristic:
==3734732== newarray : 589,632 bytes in 8 blocks
==3734732== multipleinheritance: 30,616 bytes in 51 blocks
==3734732== suppressed: 48 bytes in 1 blocks
==3734732== Rerun with --leak-check=full to see details of leaked memory
==3734732==
==3734732== For lists of detected and suppressed errors, rerun with: -s
==3734732== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
INFO> User set terminal = xterm -vb -rv
==3712778== Syscall param writev(vector[0]) points to uninitialised byte(s)
==3712778== at 0x663EE50: writev (writev.c:26)
==3712778== by 0x6D483DD: UnknownInlinedFun (xcb_conn.c:296)
==3712778== by 0x6D483DD: _xcb_conn_wait.part.0 (xcb_conn.c:553)
==3712778== by 0x6D4855F: UnknownInlinedFun (xcb_out.c:469)
==3712778== by 0x6D4855F: _xcb_out_send (xcb_out.c:470)
==3712778== by 0x6D49A68: UnknownInlinedFun (xcb_out.c:416)
==3712778== by 0x6D49A68: xcb_writev (xcb_out.c:409)
==3712778== by 0x5FB0EC9: _XSend (xcb_io.c:587)
==3712778== by 0x5FB6764: _XReply (xcb_io.c:679)
==3712778== by 0x5F9ADB0: XInternAtom (IntAtom.c:182)
==3712778== by 0x5A40E3C: gdk_x11_get_xatom_by_name_for_display (gdkproperty-x11.c:99)
==3712778== by 0x5A5619A: gdk_x11_selection_input_stream_new_async (gdkselectioninputstream-x11.c:540)
==3712778== Address 0xba117d2 is 50 bytes inside a block of size 16,384 alloc’d
==3712778== at 0x4935C13: calloc (vg_replace_malloc.c:1675)
==3712778== by 0x5F9FAF1: XOpenDisplay (OpenDis.c:241)
==3712778== by 0x5A3AA71: UnknownInlinedFun (gdkdisplay-x11.c:1443)
==3712778== by 0x5A3AA71: gdk_x11_display_open (gdkdisplay-x11.c:1427)
==3712778== by 0x5A77496: gdk_display_manager_open_display (gdkdisplaymanager.c:449)
==3712778== by 0x57595B2: UnknownInlinedFun (gdk.c:372)
==3712778== by 0x57595B2: UnknownInlinedFun (gdk.c:363)
==3712778== by 0x57595B2: UnknownInlinedFun (gtkmain.c:638)
==3712778== by 0x57595B2: gtk_init_check (gtkmain.c:620)
==3712778== by 0x575AECD: gtk_init (gtkmain.c:679)
==3712778== by 0x4031C5A: xf::Fm::Fm(char const*, bool) (fm.hh:25)
==3712778== by 0x4014179: main (xffm.cc:137)
==3712778==
==3712778== Invalid write of size 4
==3712778== at 0x576FB7D: UnknownInlinedFun (gtknotebook.c:2745)
==3712778== by 0x576FB7D: gtk_notebook_arrow_drag_leave (gtknotebook.c:3198)
==3712778== by 0x518A5F6: UnknownInlinedFun (gclosure.c:898)
==3712778== by 0x518A5F6: signal_emit_valist_unlocked (gsignal.c:3438)
==3712778== by 0x518A708: g_signal_emit_valist (gsignal.c:3277)
==3712778== by 0x518A7C3: g_signal_emit (gsignal.c:3597)
==3712778== by 0x56C9CA3: UnknownInlinedFun (gtkdropcontrollermotion.c:136)
==3712778== by 0x56C9CA3: gtk_drop_controller_motion_handle_crossing (gtkdropcontrollermotion.c:167)
==3712778== by 0x584E101: UnknownInlinedFun (gtkeventcontroller.c:417)
==3712778== by 0x584E101: gtk_widget_handle_crossing (gtkwidget.c:4773)
==3712778== by 0x575B458: gtk_synthesize_crossing_events.isra.0 (gtkmain.c:1210)
==3712778== by 0x575D5B1: UnknownInlinedFun (gtkmain.c:1478)
==3712778== by 0x575D5B1: gtk_main_do_event (gtkmain.c:1638)
==3712778== by 0x566197A: _gdk_marshal_BOOLEAN__BOXED.part.0 (gtkmarshalers.c:1607)
==3712778== by 0x5AA4927: UnknownInlinedFun (gdkmarshalers.c:244)
==3712778== by 0x5AA4927: gdk_surface_event_marshaller (gdksurface.c:442)
==3712778== by 0x5169839: g_closure_invoke (gclosure.c:835)
==3712778== by 0x518842A: signal_emit_unlocked_R.isra.0 (gsignal.c:3902)
==3712778== Address 0x1f751390 is 16 bytes before a block of size 88 alloc’d
==3712778== at 0x4935C13: calloc (vg_replace_malloc.c:1675)
==3712778== by 0x521C902: g_malloc0 (gmem.c:133)
==3712778== by 0x5168885: g_closure_new_simple (gclosure.c:208)
==3712778== by 0x5168F87: g_cclosure_new (gclosure.c:981)
==3712778== by 0x51844B0: g_signal_connect_data (gsignal.c:2534)
==3712778== by 0x577714F: update_arrow_nodes.lto_priv.0 (gtknotebook.c:3283)
==3712778== by 0x577B59B: UnknownInlinedFun (gtknotebook.c:6445)
==3712778== by 0x577B59B: gtk_notebook_set_scrollable (gtknotebook.c:6433)
==3712778== by 0x4048A6B: xf::MainWindowxf::LocalDir::mkNotebook() (window.hh:501)
==3712778== by 0x403ECC7: xf::MainWindowxf::LocalDir::contentBox(char const*) (window.hh:576)
==3712778== by 0x4037503: xf::MainWindowxf::LocalDir::MainWindow(char const*, bool) (window.hh:44)
==3712778== by 0x4031D57: xf::Fm::Fm(char const*, bool) (fm.hh:52)
==3712778== by 0x4014179: main (xffm.cc:137)
==3712778==
==3789169==
==3789169== HEAP SUMMARY:
==3789169== in use at exit: 112,597,055 bytes in 378,958 blocks
==3789169== total heap usage: 5,571,627 allocs, 5,192,669 frees, 3,541,806,965 bytes allocated
==3789169==
==3791557==
==3791557== HEAP SUMMARY:
==3791557== in use at exit: 113,682,768 bytes in 393,046 blocks
==3791557== total heap usage: 6,021,660 allocs, 5,628,614 frees, 3,930,312,487 bytes allocated
==3791557==
==3789169== LEAK SUMMARY:
==3789169== definitely lost: 213,871 bytes in 8,902 blocks
==3789169== indirectly lost: 2,837,357 bytes in 19,168 blocks
==3789169== possibly lost: 6,160,956 bytes in 54,208 blocks
==3789169== still reachable: 100,544,623 bytes in 278,591 blocks
==3789169== of which reachable via heuristic:
==3789169== newarray : 1,179,360 bytes in 17 blocks
==3789169== multipleinheritance: 31,960 bytes in 54 blocks
==3789169== suppressed: 48 bytes in 1 blocks
==3789169== Rerun with --leak-check=full to see details of leaked memory
==3789169==
==3789169== Use --track-origins=yes to see where uninitialised values come from
==3789169== For lists of detected and suppressed errors, rerun with: -s
==3789169== ERROR SUMMARY: 24 errors from 2 contexts (suppressed: 0 from 0)
==3791557== LEAK SUMMARY:
==3791557== definitely lost: 229,789 bytes in 9,530 blocks
==3791557== indirectly lost: 3,197,225 bytes in 21,295 blocks
==3791557== possibly lost: 7,439,425 bytes in 58,676 blocks
==3791557== still reachable: 99,735,977 bytes in 283,945 blocks
==3791557== of which reachable via heuristic:
==3791557== newarray : 589,728 bytes in 9 blocks
==3791557== multipleinheritance: 29,520 bytes in 50 blocks
==3791557== suppressed: 48 bytes in 1 blocks
==3791557== Rerun with --leak-check=full to see details of leaked memory
==3791557==
==3791557== Use --track-origins=yes to see where uninitialised values come from
==3791557== For lists of detected and suppressed errors, rerun with: -s
==3791557== ERROR SUMMARY: 24 errors from 2 contexts (suppressed: 0 from 0)
==3749653==
==3749653== HEAP SUMMARY:
==3749653== in use at exit: 57,622,839 bytes in 307,871 blocks
==3749653== total heap usage: 3,054,535 allocs, 2,746,664 frees, 1,784,662,821 bytes allocated
==3749653==
==3749653== LEAK SUMMARY:
==3749653== definitely lost: 61,057 bytes in 4,290 blocks
==3749653== indirectly lost: 968,306 bytes in 10,680 blocks
==3749653== possibly lost: 4,778,094 bytes in 38,845 blocks
==3749653== still reachable: 49,752,550 bytes in 240,738 blocks
==3749653== of which reachable via heuristic:
==3749653== newarray : 1,179,264 bytes in 16 blocks
==3749653== multipleinheritance: 31,960 bytes in 54 blocks
==3749653== suppressed: 48 bytes in 1 blocks
==3749653== Rerun with --leak-check=full to see details of leaked memory
==3749653==
==3749653== For lists of detected and suppressed errors, rerun with: -s
==3749653== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==3712778== Jump to the invalid address stated on the next line
==3712778== at 0x800000000: ???
==3712778== by 0x518842A: signal_emit_unlocked_R.isra.0 (gsignal.c:3902)
==3712778== by 0x518A48E: signal_emit_valist_unlocked (gsignal.c:3534)
==3712778== by 0x518A708: g_signal_emit_valist (gsignal.c:3277)
==3712778== by 0x518A7C3: g_signal_emit (gsignal.c:3597)
==3712778== by 0x584E101: UnknownInlinedFun (gtkeventcontroller.c:417)
==3712778== by 0x584E101: gtk_widget_handle_crossing (gtkwidget.c:4773)
==3712778== by 0x575B1F4: gtk_synthesize_crossing_events.isra.0 (gtkmain.c:1254)
==3712778== by 0x575D5B1: UnknownInlinedFun (gtkmain.c:1478)
==3712778== by 0x575D5B1: gtk_main_do_event (gtkmain.c:1638)
==3712778== by 0x566197A: _gdk_marshal_BOOLEAN__BOXED.part.0 (gtkmarshalers.c:1607)
==3712778== by 0x5AA4927: UnknownInlinedFun (gdkmarshalers.c:244)
==3712778== by 0x5AA4927: gdk_surface_event_marshaller (gdksurface.c:442)
==3712778== by 0x5169839: g_closure_invoke (gclosure.c:835)
==3712778== by 0x518842A: signal_emit_unlocked_R.isra.0 (gsignal.c:3902)
==3712778== Address 0x800000000 is not stack’d, malloc’d or (recently) free’d
==3712778==
==3712778==
==3712778== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==3712778== Access not within mapped region at address 0x800000000
==3712778== at 0x800000000: ???
==3712778== by 0x518842A: signal_emit_unlocked_R.isra.0 (gsignal.c:3902)
==3712778== by 0x518A48E: signal_emit_valist_unlocked (gsignal.c:3534)
==3712778== by 0x518A708: g_signal_emit_valist (gsignal.c:3277)
==3712778== by 0x518A7C3: g_signal_emit (gsignal.c:3597)
==3712778== by 0x584E101: UnknownInlinedFun (gtkeventcontroller.c:417)
==3712778== by 0x584E101: gtk_widget_handle_crossing (gtkwidget.c:4773)
==3712778== by 0x575B1F4: gtk_synthesize_crossing_events.isra.0 (gtkmain.c:1254)
==3712778== by 0x575D5B1: UnknownInlinedFun (gtkmain.c:1478)
==3712778== by 0x575D5B1: gtk_main_do_event (gtkmain.c:1638)
==3712778== by 0x566197A: _gdk_marshal_BOOLEAN__BOXED.part.0 (gtkmarshalers.c:1607)
==3712778== by 0x5AA4927: UnknownInlinedFun (gdkmarshalers.c:244)
==3712778== by 0x5AA4927: gdk_surface_event_marshaller (gdksurface.c:442)
==3712778== by 0x5169839: g_closure_invoke (gclosure.c:835)
==3712778== by 0x518842A: signal_emit_unlocked_R.isra.0 (gsignal.c:3902)
==3712778== If you believe this happened as a result of a stack
==3712778== overflow in your program’s main thread (unlikely but
==3712778== possible), you can try to increase the size of the
==3712778== main thread stack using the --main-stacksize= flag.
==3712778== The main thread stack size used in this run was 8388608.
==3712778==
==3712778== HEAP SUMMARY:
==3712778== in use at exit: 121,406,242 bytes in 383,230 blocks
==3712778== total heap usage: 8,250,117 allocs, 7,866,887 frees, 4,980,222,995 bytes allocated
==3712778==
==3712778== LEAK SUMMARY:
==3712778== definitely lost: 10,297,389 bytes in 17,448 blocks
==3712778== indirectly lost: 3,879,717 bytes in 23,379 blocks
==3712778== possibly lost: 8,588,381 bytes in 55,729 blocks
==3712778== still reachable: 95,804,635 bytes in 268,736 blocks
==3712778== of which reachable via heuristic:
==3712778== newarray : 589,632 bytes in 8 blocks
==3712778== multipleinheritance: 14,120 bytes in 36 blocks
==3712778== suppressed: 96 bytes in 2 blocks
==3712778== Rerun with --leak-check=full to see details of leaked memory
==3712778==
==3712778== Use --track-origins=yes to see where uninitialised values come from
==3712778== For lists of detected and suppressed errors, rerun with: -s
==3712778== ERROR SUMMARY: 80 errors from 3 contexts (suppressed: 0 from 0)
==3735431==
==3735431== HEAP SUMMARY:
==3735431== in use at exit: 46,206,348 bytes in 249,190 blocks
==3735431== total heap usage: 1,981,482 allocs, 1,732,292 frees, 970,102,981 bytes allocated
==3735431==
==3735431== LEAK SUMMARY:
==3735431== definitely lost: 34,063 bytes in 2,488 blocks
==3735431== indirectly lost: 496,199 bytes in 6,325 blocks
==3735431== possibly lost: 3,167,693 bytes in 26,930 blocks
==3735431== still reachable: 41,090,649 bytes in 204,211 blocks
==3735431== of which reachable via heuristic:
==3735431== newarray : 589,632 bytes in 8 blocks
==3735431== multipleinheritance: 30,616 bytes in 51 blocks
==3735431== suppressed: 48 bytes in 1 blocks
==3735431== Rerun with --leak-check=full to see details of leaked memory
==3735431==
==3735431== For lists of detected and suppressed errors, rerun with: -s
==3735431== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Apparently this is a bug in gtk_notebook_set_scrollable. If I comment out the line which is calling that function after the notebook creation, DnD with multiple tabs in the notebook seems to work fine.

From the valgrind log you can see that the invalid write of size 4 (probably a integer) comes as a consequence of gtk_notebook_set_scrollable (gtknotebook.c:6433) at precisely gtk_notebook_arrow_drag_leave (gtknotebook.c:3198).

You can report the issue in https://gitlab.gnome.org/GNOME/gtk/-/issues.

Ok. That’s done, although it is not an issue for me any more. I just dropped the scrollable tabs option from all the notebooks in xffm4.

Tracked in below issue.