RESOLVED FIXED291384
Estimated load progress out of range when downloading particular PDF or Quicken files, leading to crash
https://bugs.webkit.org/show_bug.cgi?id=291384
Summary Estimated load progress out of range when downloading particular PDF or Quick...
Michael Catanzaro
Reported 2025-04-10 13:09:30 PDT
Moving from https://gitlab.gnome.org/GNOME/epiphany/-/issues/2633 Visit https://www.canada.ca/en/immigration-refugees-citizenship/services/application/application-forms-guides/imm0272.html Try to download the PDF in Epiphany Tech Preview. WebKitGTK 2.49.1 will crash. It's a floating point rounding issue; problem is the value is 1.000402 which is out of range. The documented maximum load progress is 1.000000.
Attachments
Crash backtrace when downloading a QFX file (9.01 KB, text/plain)
2025-04-21 14:06 PDT, Jeff Fortin
no flags
Jeff Fortin
Comment 1 2025-04-21 14:06:40 PDT
Created attachment 474995 [details] Crash backtrace when downloading a QFX file It also happens for non-PDF files too, such as some banks that generate "Quicken" .QFX / .OFX files... but it only happens when downloading from their website (in my case, both if done using the main Epiphany browser or as an Epiphany web app). It does not happen if you save the file to disk (using Firefox) and then open it locally with Epiphany. This makes me suspect that maybe this is all due to some servers generating files as they go, instead of giving you a completed file to download, because: * I can't see how you'd get over 340% on a 2 kilobytes 11-lines-of-contents file like the .QFX I saw crashing; * The same banking website does not crash the browser when downloading PDF statement files: the difference there is that statements are pre-generated monthly, whereas .QFX are generated depending on a time range that the user chooses in the web interface, so presumably the server is progressively generating the data at the same time as it is pushing it over to the browser. This has been happening in Epiphany 48 and every previous version. P.S.: OFX files are essentially XML prefixed with a header of a couple lines of plain text that looks roughly like this: ``` OFXHEADER:100 DATA:OFXSGML VERSION:102 SECURITY:NONE ENCODING:USASCII CHARSET:1252 COMPRESSION:NONE OLDFILEUID:NONE NEWFILEUID:NONE <OFX><SIGNONMSGSRSV1><SONRS><STATUS><CODE>blah blah blah contents start here ```
Michael Catanzaro
Comment 2 2026-03-05 14:21:05 PST
Surprise, it's probably an Epiphany bug: (gdb) bt #0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 #1 0x00007fcbbdeeea53 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:89 #2 0x00007fcbbde9334e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #3 0x00007fcbbde7a7b3 in __GI_abort () at abort.c:77 #4 0x00007fcbbf25c2ca in _g_log_abort (breakpoint=1) at ../../../../Projects/glib/glib/gmessages.c:454 #5 0x00007fcbbf25d25b in g_logv (log_domain=0x7fcbbf3e5354 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=0x7fcbbf3e5d58 "value \"%s\" of type '%s' is invalid or out of range for property '%s' of type '%s'", args=0x7ffd56cd9548) at ../../../../Projects/glib/glib/gmessages.c:1313 #6 0x00007fcbbf25d355 in g_log (log_domain=0x7fcbbf3e5354 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=0x7fcbbf3e5d58 "value \"%s\" of type '%s' is invalid or out of range for property '%s' of type '%s'") at ../../../../Projects/glib/glib/gmessages.c:1355 #7 0x00007fcbbf3a23ab in object_set_property (object=0x2884ec00, pspec=0x288806b0, value=0x7ffd56cd9720, nqueue_is_frozen=0, user_specified=1) at ../../../../Projects/glib/gobject/gobject.c:2249 #8 0x00007fcbbf3a494d in g_object_set_valist (object=0x2884ec00, first_property_name=0x7fcbbf7dc1a8 "progress", var_args=0x7ffd56cd97b0) at ../../../../Projects/glib/gobject/gobject.c:3207 #9 0x00007fcbbf3a524f in g_object_set (_object=0x2884ec00, first_property_name=0x7fcbbf7dc1a8 "progress") at ../../../../Projects/glib/gobject/gobject.c:3383 #10 0x00007fcbbf6e62e0 in downloads_estimated_progress_cb (manager=0x285ddb80, action_bar_end=0x286e8f60) at ../../../../../epiphany/src/ephy-action-bar-end.c:121 #11 0x00007fcbbf39c434 in g_cclosure_marshal_VOID__VOID (closure=0x28976410, return_value=0x0, n_param_values=1, param_values=0x7ffd56cd9be0, invocation_hint=0x7ffd56cd9a80, marshal_data=0x0) at ../../../../Projects/glib/gobject/gmarshal.c:117 #12 0x00007fcbbf398437 in g_closure_invoke (closure=0x28976410, return_value=0x0, n_param_values=1, param_values=0x7ffd56cd9be0, invocation_hint=0x7ffd56cd9a80) at ../../../../Projects/glib/gobject/gclosure.c:916 #13 0x00007fcbbf3bbe94 in signal_emit_unlocked_R (node=0x7ffd56cd9d10, detail=0, instance=0x285ddb80, emission_return=0x0, instance_and_params=0x7ffd56cd9be0) at ../../../../Projects/glib/gobject/gsignal.c:3929 #14 0x00007fcbbf3bad73 in signal_emit_valist_unlocked (instance=0x285ddb80, signal_id=122, detail=0, var_args=0x7ffd56cd9f08) at ../../../../Projects/glib/gobject/gsignal.c:3561 #15 0x00007fcbbf3b9a67 in g_signal_emit_valist (instance=0x285ddb80, signal_id=122, detail=0, var_args=0x7ffd56cd9f08) at ../../../../Projects/glib/gobject/gsignal.c:3304 #16 0x00007fcbbf3bb322 in g_signal_emit (instance=0x285ddb80, signal_id=122, detail=0) at ../../../../Projects/glib/gobject/gsignal.c:3624 #17 0x00007fcbbf75bf9f in download_estimated_progress_changed_cb (manager=0x285ddb80) at ../../../../../epiphany/embed/ephy-downloads-manager.c:167 #18 0x00007fcbbf39dafe in g_cclosure_marshal_VOID__PARAM (closure=0x28dcbc50, return_value=0x0, n_param_values=2, param_values=0x7ffd56cda320, invocation_hint=0x7ffd56cda1c0, marshal_data=0x0) at ../../../../Projects/glib/gobject/gmarshal.c:1516 #19 0x00007fcbbf398437 in g_closure_invoke (closure=0x28dcbc50, return_value=0x0, n_param_values=2, param_values=0x7ffd56cda320, invocation_hint=0x7ffd56cda1c0) at ../../../../Projects/glib/gobject/gclosure.c:916 #20 0x00007fcbbf3bbe94 in signal_emit_unlocked_R (node=0x7ffd56cda470, detail=4597, instance=0x28d855a0, emission_return=0x0, instance_and_params=0x7ffd56cda320) at ../../../../Projects/glib/gobject/gsignal.c:3929 #21 0x00007fcbbf3bad73 in signal_emit_valist_unlocked (instance=0x28d855a0, signal_id=1, detail=4597, var_args=0x7ffd56cda668) at ../../../../Projects/glib/gobject/gsignal.c:3561 #22 0x00007fcbbf3b9a67 in g_signal_emit_valist (instance=0x28d855a0, signal_id=1, detail=4597, var_args=0x7ffd56cda668) at ../../../../Projects/glib/gobject/gsignal.c:3304 #23 0x00007fcbbf3bb322 in g_signal_emit (instance=0x28d855a0, signal_id=1, detail=4597) at ../../../../Projects/glib/gobject/gsignal.c:3624 #24 0x00007fcbbf3a1a85 in g_object_dispatch_properties_changed (object=0x28d855a0, n_pspecs=1, pspecs=0x7ffd56cda790) at ../../../../Projects/glib/gobject/gobject.c:1889 #25 0x00007fcbbf3a1d11 in g_object_notify_by_spec_internal (object=0x28d855a0, pspec=0x28d95890) at ../../../../Projects/glib/gobject/gobject.c:1994 #26 0x00007fcbbf3a1ec6 in g_object_notify_by_pspec (object=0x28d855a0, pspec=0x28d95890) at ../../../../Projects/glib/gobject/gobject.c:2100 #27 0x00007fcbba6af612 in WebKit::DownloadProxy::didReceiveData (this=0x71166, bytesWritten=6, totalBytesWritten=140513041639820, totalBytesExpectedToWrite=140513043196616) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp:151 #28 0x00007fcbb9ff74b7 in IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}::operator()<unsigned long, unsigned long, unsigned long>(unsigned long&&, unsigned long&&, unsigned long&&) const (this=<optimized out>, args=<optimized out>, args=<optimized out>, args=<optimized out>) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:138 #29 std::__invoke_impl<void, IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}, unsigned long, unsigned long, unsigned long>(std::__invoke_other, IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}&&, unsigned long&&, unsigned long&&, unsigned long&&) (__f=..., __args=<optimized out>, __args=<optimized out>, __args=<optimized out>) at /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/invoke.h:63 --Type <RET> for more, q to quit, c to continue without paging--c #30 std::__invoke<IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}, unsigned long, unsigned long, unsigned long>(IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}&&, unsigned long&&, unsigned long&&, unsigned long&&) (__fn=..., __args=<optimized out>, __args=<optimized out>, __args=<optimized out>) at /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/invoke.h:98 #31 std::__apply_impl<IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}, std::tuple<unsigned long, unsigned long, unsigned long>, 0ul, 1ul, 2ul>(IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void (unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> >(WebKit::DownloadProxy*, void (WebKit::DownloadProxy::*)(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long>&&)::{lambda((auto:1&&)...)#1}&&, std::tuple<unsigned long, unsigned long, unsigned long>&&, std::integer_sequence<unsigned long, 0ul, 1ul, 2ul>) (__f=..., __t=...) at /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/tuple:2976 #32 apply<(lambda at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:136:9), std::tuple<unsigned long, unsigned long, unsigned long> > (__f=..., __t=...) at /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/tuple:2991 #33 IPC::callMemberFunction<WebKit::DownloadProxy, WebKit::DownloadProxy, void(unsigned long, unsigned long, unsigned long), std::tuple<unsigned long, unsigned long, unsigned long> > (object=0x7fcb0150c0c0, function=<optimized out>, tuple=...) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:135 #34 IPC::handleMessage<Messages::DownloadProxy::DidReceiveData, IPC::Connection, WebKit::DownloadProxy, WebKit::DownloadProxy, void(unsigned long, unsigned long, unsigned long)> (connection=..., decoder=..., object=0x7fcb0150c0c0, function=<optimized out>) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:455 #35 WebKit::DownloadProxy::didReceiveMessage (this=0x7fcb0150c0c0, connection=..., decoder=...) at /home/mcatanzaro/Projects/.gnome-builder/projects/WebKit/builds/default-jhbuild-x86_64-main/DerivedSources/WebKit/DownloadProxyMessageReceiver.cpp:70 #36 0x00007fcbba4497d9 in IPC::MessageReceiverMap::dispatchMessage (this=<optimized out>, connection=..., decoder=...) at WTF/Headers/wtf/Ref.h:54 #37 0x00007fcbb9ffd08b in WebKit::NetworkProcessProxy::didReceiveMessage (this=0x71166, connection=..., decoder=...) at /home/mcatanzaro/Projects/.gnome-builder/projects/WebKit/builds/default-jhbuild-x86_64-main/DerivedSources/WebKit/NetworkProcessProxyMessageReceiver.cpp:310 #38 0x00007fcbba440882 in IPC::Connection::dispatchMessage (this=this@entry=0x7fcba3056e00, decoder=...) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1413 #39 0x00007fcbba440b13 in IPC::Connection::dispatchMessage (this=0x7fcba3056e00, message=...) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1473 #40 0x00007fcbba440c19 in IPC::Connection::dispatchOneIncomingMessage (this=<optimized out>) at /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1547 #41 0x00007fcbb7e1ffc5 in WTF::Function<void()>::operator() (this=0x7ffd56cdadb8) at /home/mcatanzaro/Projects/WebKit/Source/WTF/wtf/Function.h:103 #42 WTF::RunLoop::performWork (this=0x7fcba3018180) at /home/mcatanzaro/Projects/WebKit/Source/WTF/wtf/RunLoop.cpp:145 #43 0x00007fcbb7ee10e9 in WTF::RunLoop::RunLoop()::$_0::operator()(void*) const (userData=0x71166, userData@entry=0x7fcba3018180, this=<optimized out>) at /home/mcatanzaro/Projects/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:153 #44 WTF::RunLoop::RunLoop()::$_0::__invoke(void*) (userData=0x71166, userData@entry=0x7fcba3018180) at /home/mcatanzaro/Projects/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:152 #45 0x00007fcbb7edfa89 in WTF::RunLoop::$_3::operator() (source=0x28001bd0, callback=0x7fcbb7ee10e0 <WTF::RunLoop::RunLoop()::$_0::__invoke(void*)>, userData=0x7fcba3018180, this=<optimized out>) at /home/mcatanzaro/Projects/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:116 #46 WTF::RunLoop::$_3::__invoke (source=0x28001bd0, callback=0x7fcbb7ee10e0 <WTF::RunLoop::RunLoop()::$_0::__invoke(void*)>, userData=0x7fcba3018180) at /home/mcatanzaro/Projects/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:89 #47 0x00007fcbbf24f89e in g_main_dispatch (context=0x27fa54e0) at ../../../../Projects/glib/glib/gmain.c:3565 #48 0x00007fcbbf250cc8 in g_main_context_dispatch_unlocked (context=0x27fa54e0) at ../../../../Projects/glib/glib/gmain.c:4425 #49 0x00007fcbbf250e88 in g_main_context_iterate_unlocked (context=0x27fa54e0, block=1, dispatch=1, self=0x27faa290) at ../../../../Projects/glib/glib/gmain.c:4490 #50 0x00007fcbbf250fb3 in g_main_context_iteration (context=0x27fa54e0, may_block=1) at ../../../../Projects/glib/glib/gmain.c:4556 #51 0x00007fcbbf4f6151 in g_application_run (application=0x27ff4800, argc=1, argv=0x7ffd56cdb248) at ../../../../Projects/glib/gio/gapplication.c:2742 #52 0x00000000004020f9 in main (argc=1, argv=0x7ffd56cdb248) at ../../../../../epiphany/src/ephy-main.c:455
Michael Catanzaro
Comment 3 2026-03-06 08:51:36 PST
The Epiphany code looks safe: gdouble ephy_downloads_manager_get_estimated_progress (EphyDownloadsManager *manager) { GList *l; guint n_active = 0; gdouble progress = 0; g_assert (EPHY_IS_DOWNLOADS_MANAGER (manager)); for (l = manager->downloads; l; l = g_list_next (l)) { EphyDownload *download = EPHY_DOWNLOAD (l->data); if (!ephy_download_is_active (download)) continue; n_active++; progress += webkit_download_get_estimated_progress (ephy_download_get_webkit_download (download)); } return n_active > 0 ? progress / n_active : 1; }
Michael Catanzaro
Comment 4 2026-03-06 08:55:52 PST
Yeah, problem is webkit_download_get_estimated_progress() directly returns the invalid value.
Michael Catanzaro
Comment 5 2026-03-06 09:09:57 PST
Added debug prints: priv->currentSize=2280565 contentLength=2272675 result=1.003472 We probably should not trust the Content-Length header to be accurate.
Michael Catanzaro
Comment 6 2026-03-06 11:52:23 PST
Michael Catanzaro
Comment 7 2026-03-11 12:50:02 PDT
For the record: the actual size of this PDF is 2282807 bytes. But the server actually doesn't send any Content-Length header at all: $ curl -I https://www.canada.ca/content/dam/ircc/documents/pdf/english/kits/forms/imm0272/01-02-2025/imm0272e.pdf HTTP/2 200 content-type: application/pdf server: Apache x-dispatcher: dispatcher1cacentral1-29431743 x-vhost: publish x-content-type-options: nosniff last-modified: Tue, 25 Mar 2025 19:47:47 GMT date: Wed, 11 Mar 2026 19:45:06 GMT set-cookie: aka-ca-site-token=4718d0173492000042c6b1690e0000001eb70100; path=/; secure alt-svc: h3=":443"; ma=93600 access-control-allow-origin: * x-frame-options: DENY strict-transport-security: max-age=31536000 akamai-grn: 0.4718d017.1773258302.6d3747ff server-timing: ak_p; desc="1773258302942_399513671_1832339455_302821_8529_11_29_15";dur=1 So now I wonder where the content length value is coming from. Need to make sure I'm not just papering over a bug somewhere else....
Michael Catanzaro
Comment 8 2026-03-16 14:29:16 PDT
OK, mystery solved. Problem is `curl -I` does a HEAD request, so the server simply does not send Content-Length. So that was a bad way to test things.
EWS
Comment 9 2026-03-16 14:50:56 PDT
Committed 309350@main (56a52301da16): <https://commits.webkit.org/309350@main> Reviewed commits have been landed. Closing PR #60080 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.