fanglingsu / vimb

Vimb - the vim like browser is a webkit based web browser that behaves like the vimperator plugin for the firefox and usage paradigms from the great editor vim. The goal of vimb is to build a completely keyboard-driven, efficient and pleasurable browsing-experience.
https://fanglingsu.github.io/vimb/
GNU General Public License v3.0
1.33k stars 99 forks source link

`:sh echo hello` causes vimb crash after saying "`g_variant_get: assertion 'value != NULL' failed`" followed by "`double free`" #745

Closed falsifian closed 6 months ago

falsifian commented 1 year ago

EDIT: I've narrowed down the cause; see https://github.com/fanglingsu/vimb/issues/745#issuecomment-1614950018

Note that this is actually vimb 3.7.0 despite the below --bug-info output; see #743.

$ vimb --bug-info
Version:         3.6.0
WebKit compile:  2.40.2
WebKit run:      2.40.2
GTK compile:     3.24.38
GTK run:         3.24.38
libsoup compile: 3.4.2
libsoup run:     3.4.2
Extension dir:   /usr/local/lib/vimb

Possibly relevant: OpenBSD's libc makes some effort to detect double frees and use after frees. So, if this crash is not observed on other platforms, maybe the double free is still happening undetected? I am curious whether others are seeing at least the g_variant_get: assertion 'value != NULL' failed in the output (stderr?) of vimb.

Steps to reproduce

With Vimb 3.7.0 on OpenBSD-current (amd64), after logging in to Facebook, I can trigger the following behaviour consistently with :open facebook.com. (The crash happens right away upon loading the page; no interaction is needed.) If it would help, I can try to find other sites that consistently trigger this; facebook.com is just the first one where I noticed it happens every single time.

Expected behaviour

vimb doesn't die

Actual behaviour

Here is what I see in the terminal:

$ vimb --no-maximize 
** Message: 16:11:22.779: Could not read style file: /home/falsifian/.config/vimb/style.css

** (vimb:43081): WARNING **: 16:11:29.669: Failed dbus method EvalJs: The connection is closed

(vimb:43081): GLib-CRITICAL **: 16:11:29.669: g_variant_get: assertion 'value != NULL' failed
vimb(43081) in free(): double free 0x480e672a8f0
Abort trap (core dumped) 

Here are backtraces I generated by opening the core dump with gdb and using the bt command. There are three of them, based on opening vimb three separate times and navigating to facebook.com in each case.

1.

#0  thrkill () at /tmp/-:3
#1  0x7a10f51e7ae17e5c in ?? ()
#2  0x00000480e2e84c22 in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51
#3  0x00000480e2e7be4e in wrterror (d=0x480e4df98f8, 
    msg=0x480e2df08eb "double free %p")
    at /usr/src/lib/libc/stdlib/malloc.c:313
#4  0x00000480e2e8101e in find_chunknum (d=0x480e4df98f8, info=0x4814e88ef78, 
    check=<error reading variable: Cannot access memory at address 0x0>, 
    ptr=<optimized out>) at /usr/src/lib/libc/stdlib/malloc.c:1183
#5  free_bytes (d=0x480e4df98f8, r=0x4811f895d60, ptr=0x480be4b35e0)
    at /usr/src/lib/libc/stdlib/malloc.c:1203
#6  0x00000480e2e7d06b in ofree (argpool=0x480be4b3930, p=<optimized out>, 
    clear=<optimized out>, check=<optimized out>, argsz=<optimized out>)
    at /usr/src/lib/libc/stdlib/malloc.c:1612
#7  0x00000480e2e7cb43 in _libc_free (ptr=0x480e671d360)
    at /usr/src/lib/libc/stdlib/malloc.c:1641
#8  0x0000048094793fee in g_source_destroy_internal ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#9  0x0000048094798464 in g_main_context_dispatch ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#10 0x0000048094798757 in g_main_context_iterate ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#11 0x0000048094798b6a in g_main_loop_run ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#12 0x00000480b1b846fc in gdbus_shared_thread_func ()
   from /usr/local/lib/libgio-2.0.so.4200.17
#13 0x00000480947ccae9 in g_thread_proxy ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#14 0x00000480aadb7cd5 in _rthread_start (v=<optimized out>)
    at /usr/src/lib/librthread/rthread.c:96
#15 0x00000480e2e4561a in __tfork_thread ()
    at /usr/src/lib/libc/arch/amd64/sys/tfork_thread.S:86

2.

#0  thrkill () at /tmp/-:3
#1  0x78051481aa24534d in ?? ()
#2  0x00000194d1d67c22 in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51
#3  0x00000194d1d5ee4e in wrterror (d=0x194dae6b668, 
    msg=0x194d1cd38eb "double free %p")
    at /usr/src/lib/libc/stdlib/malloc.c:313
#4  0x00000194d1d6401e in find_chunknum (d=0x194dae6b668, info=0x194cd551ea0, 
    check=<error reading variable: Cannot access memory at address 0x0>, 
    ptr=<optimized out>) at /usr/src/lib/libc/stdlib/malloc.c:1183
#5  free_bytes (d=0x194dae6b668, r=0x1954c8d0af8, ptr=0x7e39071a2400)
    at /usr/src/lib/libc/stdlib/malloc.c:1203
#6  0x00000194d1d6006b in ofree (argpool=0x7e39071a2750, p=<optimized out>, 
    clear=<optimized out>, check=<optimized out>, argsz=<optimized out>)
    at /usr/src/lib/libc/stdlib/malloc.c:1612
#7  0x00000194d1d5fb43 in _libc_free (ptr=0x194e4a5cd90)
    at /usr/src/lib/libc/stdlib/malloc.c:1641
#8  0x00000194c7310e67 in g_source_unref_internal ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#9  0x00000194c731530a in g_main_context_dispatch ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#10 0x00000194c7315757 in g_main_context_iterate ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#11 0x00000194c7315b6a in g_main_loop_run ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#12 0x00000195562e71ec in gtk_main () from /usr/local/lib/libgtk-3.so.2201.0
#13 0x0000019263154d5d in main ()
quit
#0  thrkill () at /tmp/-:3
#1  0xbb3556544b8db918 in ?? ()
#2  0x0000081838b5ac22 in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51
#3  0x0000081838b51e4e in wrterror (d=0x81789fcf6d8, 
    msg=0x81838ac68eb "double free %p")
    at /usr/src/lib/libc/stdlib/malloc.c:313
#4  0x0000081838b5701e in find_chunknum (d=0x81789fcf6d8, info=0x8181906fd80, 
    check=<error reading variable: Cannot access memory at address 0x0>, 
    ptr=<optimized out>) at /usr/src/lib/libc/stdlib/malloc.c:1183
#5  free_bytes (d=0x81789fcf6d8, r=0x817b9a310d0, ptr=0x8177fca18d0)
    at /usr/src/lib/libc/stdlib/malloc.c:1203
#6  0x0000081838b5306b in ofree (argpool=0x8177fca1c20, p=<optimized out>, 
    clear=<optimized out>, check=<optimized out>, argsz=<optimized out>)
    at /usr/src/lib/libc/stdlib/malloc.c:1612
#7  0x0000081838b52b43 in _libc_free (ptr=0x81842d383a0)
    at /usr/src/lib/libc/stdlib/malloc.c:1641
#8  0x00000817c8614fee in g_source_destroy_internal ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#9  0x00000817c8619464 in g_main_context_dispatch ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#10 0x00000817c8619757 in g_main_context_iterate ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#11 0x00000817c8619b6a in g_main_loop_run ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#12 0x00000817b65746fc in gdbus_shared_thread_func ()
   from /usr/local/lib/libgio-2.0.so.4200.17
#13 0x00000817c864dae9 in g_thread_proxy ()
   from /usr/local/lib/libglib-2.0.so.4201.10
#14 0x0000081867daecd5 in _rthread_start (v=<optimized out>)
    at /usr/src/lib/librthread/rthread.c:96
#15 0x0000081838b1b61a in __tfork_thread ()
    at /usr/src/lib/libc/arch/amd64/sys/tfork_thread.S:86
quit

3.

#0  thrkill () at /tmp/-:3
#1  0x4d1c631a488bbfa8 in ?? ()
#2  0x0000069f5de58c22 in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51
#3  0x0000069f5de4fe4e in wrterror (d=0x69eb89a6120, 
    msg=0x69f5ddc48eb "double free %p")
    at /usr/src/lib/libc/stdlib/malloc.c:313
#4  0x0000069f5de51211 in ofree (argpool=0x7da383700080, p=<optimized out>, 
    clear=<optimized out>, check=<optimized out>, argsz=<optimized out>)
    at /usr/src/lib/libc/stdlib/malloc.c:696
#5  0x0000069f5de50b43 in _libc_free (ptr=0x69e6e8b76e0)
    at /usr/src/lib/libc/stdlib/malloc.c:1641
#6  0x0000069c5e5549f2 in ex_shellcmd ()
#7  0x0000069c5e553e82 in ex_run_string ()
#8  0x0000069c5e550f00 in autocmd_run ()
#9  0x0000069c5e55a7b6 in on_webview_load_changed ()
#10 0x0000069e718d3bc5 in g_closure_invoke ()
   from /usr/local/lib/libgobject-2.0.so.4200.17
#11 0x0000069e718ee51d in signal_emit_unlocked_R ()
   from /usr/local/lib/libgobject-2.0.so.4200.17
#12 0x0000069e718ef642 in g_signal_emit_valist ()
   from /usr/local/lib/libgobject-2.0.so.4200.17
#13 0x0000069e718efa15 in g_signal_emit ()
   from /usr/local/lib/libgobject-2.0.so.4200.17
#14 0x0000069efc3bafa8 in webkitWebViewLoadChanged(_WebKitWebView*, WebKitLoadEvent) () from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#15 0x0000069efc2ad92e in WebKit::WebPageProxy::didCommitLoadForFrame(WebCore::ProcessQualified<WTF::ObjectIdentifier<WebCore::FrameIdentifierType> >, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, unsigned long long, WTF::String const&, bool, WebCore::FrameLoadType, WebCore::CertificateInfo const&, bool, bool, bool, WebCore::HasInsecureContent, WebCore::MouseEventPolicy, WebKit::UserData const&) () from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#16 0x0000069efc2acda7 in WebKit::WebPageProxy::commitProvisionalPage(WebCore::ProcessQualified<WTF::ObjectIdentifier<WebCore::FrameIdentifierType> >, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, unsigned long long, WTF::String const&, bool, WebCore::FrameLoadType, WebCore::CertificateInfo const&, bool, bool, bool, WebCore::HasInsecureContent, WebCore::MouseEventPolicy, WebKit::UserData const&) () from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#17 0x0000069efc26d030 in WebKit::ProvisionalPageProxy::didCommitLoadForFrame(WebCore::ProcessQualified<WTF::ObjectIdentifier<WebCore::FrameIdentifierType> >, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, unsigned long long, WTF::String const&, bool, WebCore::FrameLoadType, WebCore::CertificateInfo const&, bool, bool, bool, WebCore::HasInsecureContent, WebCore::MouseEventPolicy, WebKit::UserData const&) () from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#18 0x0000069efc2749e0 in void IPC::handleMessage<Messages::WebPageProxy::DidCommitLoadForFrame, WebKit::ProvisionalPageProxy, WebKit::ProvisionalPageProxy, void (WebCore::ProcessQualified<WTF::ObjectIdentifier<WebCore::FrameIdentifierType> >, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, unsigned long long, WTF::String const&, bool, WebCore::FrameLoadType, WebCore::CertificateInfo const&, bool, bool, bool, WebCore::HasInsecureContent, WebCore::MouseEventPolicy, WebKit::UserData const&)>(IPC::Connection&, IPC::Decoder&, WebKit::ProvisionalPageProxy*, void (WebKit::ProvisionalPageProxy::*)(WebCore::ProcessQualified<WTF::ObjectIdentifier<WebCore::FrameIdentifierType> >, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, unsigned long long, WTF::String const&, bool, WebCore::FrameLoadType, WebCore::CertificateInfo const&, bool, bool, bool, WebCore::HasInsecureContent, WebCore::MouseEventPolicy, WebKit::UserData const&)) ()
   from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#19 0x0000069efc1f32f8 in IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) () from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#20 0x0000069efc30b7c0 in non-virtual thunk to WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) ()
   from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#21 0x0000069efc1ea2b1 in IPC::Connection::dispatchMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >) ()
   from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#22 0x0000069efc1ea82d in IPC::Connection::dispatchIncomingMessages() ()
   from /usr/local/lib/libwebkit2gtk-4.1.so.3.9
#23 0x0000069e7c597db0 in WTF::RunLoop::performWork() ()
   from /usr/local/lib/libjavascriptcoregtk-4.1.so.3.9
#24 0x0000069e7c60c19b in WTF::RunLoop::RunLoop()::$_1::__invoke(void*) ()
   from /usr/local/lib/libjavascriptcoregtk-4.1.so.3.9
#25 0x0000069e7c60b3c5 in WTF::RunLoop::$_0::__invoke(_GSource*, int (*)(void*), void*) () from /usr/local/lib/libjavascriptcoregtk-4.1.so.3.9
#26 0x0000069f1c8953ef in g_main_context_dispatch () from /usr/local/lib/libglib-2.0.so.4201.10
#27 0x0000069f1c895757 in g_main_context_iterate () from /usr/local/lib/libglib-2.0.so.4201.10
#28 0x0000069f1c895b6a in g_main_loop_run () from /usr/local/lib/libglib-2.0.so.4201.10
#29 0x0000069eedd771ec in gtk_main () from /usr/local/lib/libgtk-3.so.2201.0
#30 0x0000069c5e559d5d in main ()
falsifian commented 1 year ago

Found another page that triggers this consistently: Github's two-factor-authentication.

If I go to https://www.github.com/login and enter my username and password, then vimb starts loading the page to enter my second factor, and then crashes.

(A minor difference in this case is that I also see ** (WebKitWebProcess:58042): WARNING **: 16:47:33.921: Failed to emit signal 'VerticalScroll': The connection is closed after the vimb process aborts. I guess that indicates the webkit process is still alive when vimb dies?)

falsifian commented 1 year ago

Another piece of the puzzle:

I have the following in my vimb config:

autocmd LoadCommitted * shellcmd /bin/sh -c 'printf "%s LC %s\n" "\$(date -u +%FT%TZ)" "$VIMB_URI" >> ~/var/log/vimb'

If I comment out that line from ~/.config/vimb/config, these crashes do not happen.

falsifian commented 1 year ago

Okay, this is enough to trigger the crash:

  1. Go to https://www.facebook.com/ (I'm logged in)
  2. :sh echo hello
fanglingsu commented 1 year ago

@falsifian Could be an issue in https://github.com/fanglingsu/vimb/blob/master/src/ex.c#L1105. Does it make a difference when you run the command asynchron by shellcmd! /bin/sh -c '...' (! changes shellcmd to not consider the output and can therefore run in backgorund).

falsifian commented 1 year ago

No, it still crashes with :sh!.

The assertion error is being triggered by the call to g_variant_get in ext_proxy_get_current_selection when it is called by ex_shellcmd; the jsreturn variable is NULL. I guess ext_proxy_eval_script_sync is returning NULL and that should be checked. (I found this out with gdb + G_DEBUG=fatal-criticals in the environment.) I don't know if this is related to the double free.