Bug 2172377
Summary: | Crash under Curl_fillreadbuffer() | ||
---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | Milan Crha <mcrha> |
Component: | syncevolution | Assignee: | Milan Crha <mcrha> |
Status: | CLOSED ERRATA | QA Contact: | Fedora Extras Quality Assurance <extras-qa> |
Severity: | unspecified | Docs Contact: | |
Priority: | unspecified | ||
Version: | 37 | CC: | kdudka, lzaoral, mcrha, msekleta, patrick.ohly, paul, pyz, svashisht, vmihalko |
Target Milestone: | --- | ||
Target Release: | --- | ||
Hardware: | Unspecified | ||
OS: | Unspecified | ||
URL: | https://retrace.fedoraproject.org/faf/reports/628225/ | ||
Whiteboard: | |||
Fixed In Version: | syncevolution-2.0.0-8.fc38 syncevolution-2.0.0-6.fc37 | Doc Type: | If docs needed, set a value |
Doc Text: | Story Points: | --- | |
Clone Of: | Environment: | ||
Last Closed: | 2023-03-11 03:13:15 UTC | Type: | Bug |
Regression: | --- | Mount Type: | --- |
Documentation: | --- | CRM: | |
Verified Versions: | Category: | --- | |
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
Cloudforms Team: | --- | Target Upstream Version: | |
Embargoed: |
Description
Milan Crha
2023-02-22 07:10:53 UTC
(In reply to Milan Crha from comment #0) > The crash is deep in curl, thus I fill this here. Note gdb cannot find > appropriate debuginfo even with debuginfod enabled, which is kinda weird. That is unfortunate. I would need to know at least where `readfunc` points to. > I can share credentials for the memotoo test account in private, if needed, > to make it easier for you to reproduce. Yes, please. (In reply to Kamil Dudka from comment #1) > > I can share credentials for the memotoo test account in private, if needed, > > to make it easier for you to reproduce. > > Yes, please. Sent by email, as a reply to this bug message. This seems to be a bug of syncevolution. It sets CURLOPT_READDATA to address of the CurlTransportAgent object and, at the same time, it sets CURLOPT_READFUNCTION to NULL, which makes libcurl call fread() with an invalid FILE* handle. There is exactly the same problem with CURLOPT_WRITEDATA and CURLOPT_WRITEFUNCTION. The bug seems to be introduced with the following upstream commit: https://gitlab.freedesktop.org/SyncEvolution/syncevolution/-/commit/623397c674ac5a98a0b5cbc73ef918780c718d19 If I revert the hunks in CurlTransportAgent.cpp and CurlTransportAgent.h of the commit above, syncevolution does not crash any more: kdudka@f37 /tmp % export LD_LIBRARY_PATH=/home/kdudka/curl/curl-7.85.0/build-full/lib/.libs:/home/kdudka/syncevolution/syncevolution-2.0.0/src/syncevo/.libs kdudka@f37 /tmp % gdb /home/kdudka/syncevolution//syncevolution-2.0.0/src/.libs/syncevolution --ex "r --daemon=no --run --sync refresh-from-local memotoo" GNU gdb (GDB) Fedora Linux 12.1-7.fc37 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /home/kdudka/syncevolution//syncevolution-2.0.0/src/.libs/syncevolution... Starting program: /home/kdudka/syncevolution/syncevolution-2.0.0/src/.libs/syncevolution --daemon=no --run --sync refresh-from-local memotoo This GDB supports auto-downloading debuginfo from the following URLs: https://debuginfod.fedoraproject.org/ Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". [New Thread 0x7ffff2def6c0 (LWP 76603)] [New Thread 0x7ffff25ee6c0 (LWP 76604)] [New Thread 0x7ffff1ded6c0 (LWP 76605)] [New Thread 0x7ffff15ec6c0 (LWP 76606)] [New Thread 0x7ffff0cff6c0 (LWP 76607)] [New Thread 0x7fffdbfff6c0 (LWP 76616)] [New Thread 0x7fffdb7fe6c0 (LWP 76643)] [Thread 0x7fffdb7fe6c0 (LWP 76643) exited] [INFO] addressbook: starting first time sync from client (peer is server) [INFO] calendar: starting first time sync from client (peer is server) [INFO] memo: starting first time sync from client (peer is server) [INFO] todo: starting first time sync from client (peer is server) [INFO] creating complete data backup of datastore addressbook before sync (enabled with dumpData and needed for printChanges) Local data changes to be applied during synchronization: *** addressbook *** [Detaching after vfork from child process 76647] Comparison was impossible. [INFO] creating complete data backup of datastore calendar before sync (enabled with dumpData and needed for printChanges) *** calendar *** [Detaching after vfork from child process 76654] Comparison was impossible. [INFO] creating complete data backup of datastore memo before sync (enabled with dumpData and needed for printChanges) *** memo *** [Detaching after vfork from child process 76660] Comparison was impossible. [INFO] creating complete data backup of datastore todo before sync (enabled with dumpData and needed for printChanges) *** todo *** [Detaching after vfork from child process 76666] Comparison was impossible. [INFO] addressbook: started [INFO] calendar: started [INFO] memo: started [INFO] todo: started [INFO] addressbook: first time sync done successfully [INFO] calendar: first time sync done successfully [INFO] memo: first time sync done successfully [INFO] todo: first time sync done successfully [INFO] creating complete data backup after sync (enabled with dumpData and needed for printChanges) Synchronization successful. Changes applied during synchronization: +---------------|-----------------------|-----------------------|-CON-+ | | LOCAL | REMOTE | FLI | | Source | NEW | MOD | DEL | ERR | NEW | MOD | DEL | ERR | CTS | +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | addressbook | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | refresh-from-local, 0 KB sent by client, 0 KB received | | item(s) in database backup: 0 before sync, 0 after it | +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | calendar | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | refresh-from-local, 0 KB sent by client, 0 KB received | | item(s) in database backup: 0 before sync, 0 after it | +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | memo | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | refresh-from-local, 0 KB sent by client, 0 KB received | | item(s) in database backup: 0 before sync, 0 after it | +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | todo | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | refresh-from-local, 0 KB sent by client, 0 KB received | | item(s) in database backup: 0 before sync, 0 after it | +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | start Tue Feb 28 09:26:11 2023, duration 0:01min | | synchronization completed successfully | +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+ Data modified locally during synchronization: *** addressbook *** [Detaching after vfork from child process 76679] Comparison was impossible. *** calendar *** [Detaching after vfork from child process 76681] Comparison was impossible. *** memo *** [Detaching after vfork from child process 76683] Comparison was impossible. *** todo *** [Detaching after vfork from child process 76685] Comparison was impossible. [Thread 0x7ffff1ded6c0 (LWP 76605) exited] [Thread 0x7fffdbfff6c0 (LWP 76616) exited] [Thread 0x7ffff15ec6c0 (LWP 76606) exited] [Thread 0x7ffff25ee6c0 (LWP 76604) exited] [Thread 0x7ffff2def6c0 (LWP 76603) exited] [Thread 0x7ffff5f1e880 (LWP 76600) exited] [Thread 0x7ffff0cff6c0 (LWP 76607) exited] [New process 76600] [Inferior 1 (process 76600) exited normally] Thank you for the detailed information. I'm moving this to the syncevolution and will let the upstream folks know. > it sets CURLOPT_READFUNCTION to NULL ... There is exactly the same problem with CURLOPT_WRITEDATA and CURLOPT_WRITEFUNCTION.
That is odd.
The relevant curl calls are:
auto readDataCallback = [] (void *buffer, size_t size, size_t nmemb, void *stream) noexcept {
return static_cast<CurlTransportAgent *>(stream)->readData(buffer, size * nmemb);
};
auto writeDataCallback = [] (void *buffer, size_t size, size_t nmemb, void *stream) noexcept {
return static_cast<CurlTransportAgent *>(stream)->writeData(buffer, size * nmemb);
};
if ((code = curl_easy_setopt(m_easyHandle, CURLOPT_NOPROGRESS, false)) ||
(code = curl_easy_setopt(m_easyHandle, CURLOPT_PROGRESSFUNCTION, progressCallback)) ||
(code = curl_easy_setopt(m_easyHandle, CURLOPT_WRITEFUNCTION, writeDataCallback)) ||
Why should the write function be NULL here? Did you see in a debugger that it was NULL?
Yes, I did. The pointer to SyncEvo::CurlTransportAgent::progressCallback(void*, double, double, double, double) is correctly passed to CURLOPT_PROGRESSFUNCTION whereas CURLOPT_WRITEFUNCTION and CURLOPT_READFUNCTION get a NULL pointer from syncevolution (unless the mentioned patch is reverted): % gdb syncevolution --ex "r --daemon=no --run --sync refresh-from-local memotoo" GNU gdb (GDB) Fedora Linux 12.1-7.fc37 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from syncevolution... Reading symbols from /usr/lib/debug/usr/bin/syncevolution-2.0.0-5.fc37.x86_64.debug... Starting program: /usr/bin/syncevolution --daemon=no --run --sync refresh-from-local memotoo [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". [New Thread 0x7ffff2def6c0 (LWP 77200)] [New Thread 0x7ffff25ee6c0 (LWP 77201)] [New Thread 0x7ffff1ded6c0 (LWP 77202)] [New Thread 0x7ffff15ec6c0 (LWP 77203)] [New Thread 0x7ffff0cff6c0 (LWP 77204)] [New Thread 0x7fffdbfff6c0 (LWP 77213)] [New Thread 0x7fffdb7fe6c0 (LWP 77240)] [Thread 0x7fffdb7fe6c0 (LWP 77240) exited] Thread 1 "syncevolution" received signal SIGABRT, Aborted. __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 44 return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0; (gdb) break curl_easy_setopt Breakpoint 1 at 0x7ffff7012a3e: file ../../lib/setopt.c, line 3185. (gdb) run Starting program: /usr/bin/syncevolution --daemon=no --run --sync refresh-from-local memotoo [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". [New Thread 0x7ffff2def6c0 (LWP 77246)] [New Thread 0x7fffea5ee6c0 (LWP 77247)] [New Thread 0x7ffff25ee6c0 (LWP 77248)] [New Thread 0x7ffff1ded6c0 (LWP 77249)] [New Thread 0x7ffff15006c0 (LWP 77250)] [New Thread 0x7ffff0cff6c0 (LWP 77253)] Thread 1 "syncevolution" hit Breakpoint 1, curl_easy_setopt (data=0x5555567b05f0, tag=CURLOPT_NOPROGRESS) at ../../lib/setopt.c:3185 3185 { (gdb) cont Continuing. Thread 1 "syncevolution" hit Breakpoint 1, curl_easy_setopt (data=0x5555567b05f0, tag=CURLOPT_PROGRESSFUNCTION) at ../../lib/setopt.c:3185 3185 { (gdb) step 3189 if(!data) (gdb) 3192 va_start(arg, tag); (gdb) 3194 result = Curl_vsetopt(data, tag, arg); (gdb) Curl_vsetopt (data=0x5555567b05f0, option=CURLOPT_PROGRESSFUNCTION, param=0x7fffffffc4f0) at ../../lib/setopt.c:235 235 { (gdb) 237 CURLcode result = CURLE_OK; (gdb) 242 switch(option) { (gdb) 1571 data->set.fprogress = va_arg(param, curl_progress_callback); (gdb) 1572 if(data->set.fprogress) (gdb) print data->set.fprogress $1 = (curl_progress_callback) 0x7ffff7cc81e0 <SyncEvo::CurlTransportAgent::progressCallback(void*, double, double, double, double)> (gdb) cont Continuing. Thread 1 "syncevolution" hit Breakpoint 1, curl_easy_setopt (data=0x5555567b05f0, tag=CURLOPT_WRITEFUNCTION) at ../../lib/setopt.c:3185 3185 { (gdb) step 3189 if(!data) (gdb) 3192 va_start(arg, tag); (gdb) 3194 result = Curl_vsetopt(data, tag, arg); (gdb) Curl_vsetopt (data=0x5555567b05f0, option=CURLOPT_WRITEFUNCTION, param=0x7fffffffc4f0) at ../../lib/setopt.c:235 235 { (gdb) 237 CURLcode result = CURLE_OK; (gdb) 242 switch(option) { (gdb) 1689 data->set.fwrite_func = va_arg(param, curl_write_callback); (gdb) 1690 if(!data->set.fwrite_func) (gdb) print data->set.fwrite_func $2 = (curl_write_callback) 0x0 (gdb) cont Continuing. Thread 1 "syncevolution" hit Breakpoint 1, curl_easy_setopt (data=0x5555567b05f0, tag=CURLOPT_WRITEDATA) at ../../lib/setopt.c:3185 3185 { (gdb) Continuing. Thread 1 "syncevolution" hit Breakpoint 1, curl_easy_setopt (data=0x5555567b05f0, tag=CURLOPT_READFUNCTION) at ../../lib/setopt.c:3185 3185 { (gdb) step 3189 if(!data) (gdb) 3192 va_start(arg, tag); (gdb) 3194 result = Curl_vsetopt(data, tag, arg); (gdb) Curl_vsetopt (data=0x5555567b05f0, option=CURLOPT_READFUNCTION, param=0x7fffffffc4f0) at ../../lib/setopt.c:235 235 { (gdb) 237 CURLcode result = CURLE_OK; (gdb) 242 switch(option) { (gdb) 1698 data->set.fread_func_set = va_arg(param, curl_read_callback); (gdb) 1699 if(!data->set.fread_func_set) { (gdb) print data->set.fread_func_set $3 = (curl_read_callback) 0x0 Thanks to Lukáš Zaoral for consultation regarding the C++ lambda syntax! The following patch seems to fix it: --- a/src/syncevo/CurlTransportAgent.cpp +++ b/src/syncevo/CurlTransportAgent.cpp @@ -47,10 +47,10 @@ CurlTransportAgent::CurlTransportAgent() : * its read callback and reply is stored in write callback */ CURLcode code; - auto readDataCallback = [] (void *buffer, size_t size, size_t nmemb, void *stream) noexcept { + auto readDataCallback = +[] (void *buffer, size_t size, size_t nmemb, void *stream) noexcept { return static_cast<CurlTransportAgent *>(stream)->readData(buffer, size * nmemb); }; - auto writeDataCallback = [] (void *buffer, size_t size, size_t nmemb, void *stream) noexcept { + auto writeDataCallback = +[] (void *buffer, size_t size, size_t nmemb, void *stream) noexcept { return static_cast<CurlTransportAgent *>(stream)->writeData(buffer, size * nmemb); }; if ((code = curl_easy_setopt(m_easyHandle, CURLOPT_NOPROGRESS, false)) || The problem is that C++ lambdas cannot be used directly with curl_easy_setopt because it is defined as a variadic function [1]. Therefore, no implicit conversions to a function pointer were made using their conversion operators and the lambdas were passed directly to the cURL C API. The patch in Comment 7 explicitly enforces the implicit conversion to a function pointer. [1] https://github.com/curl/curl/blob/master/include/curl/easy.h#L42 Thanks for the analysis and explanation. I wasn't aware of this [] vs +[] difference. My testing of SyncEvolution seems to have a gap here: I am testing on different distros, but not in different build configurations. libcurl hasn't been the default for a while now, so that part didn't get covered. (In reply to Patrick Ohly from comment #9) > libcurl hasn't been the default for a while now, so that part didn't get covered. I'm sorry about that. I switched to libcurl in Fedora due to a need to move away from libsoup2. The SyncEvolution does not support libsoup3, thus the easiest option was to switch to libcurl. Some other projects did that too, if I recall correctly (not an excuse, just a note). And it should have worked, if it wasn't for this bug - sorry for that! You can patch the Fedora binaries as suggested above while I work on a new upstream release. Right, I'm building an update now. The bug will be updated when it's ready. FEDORA-2023-f61fbd10ad has been submitted as an update to Fedora 37. https://bodhi.fedoraproject.org/updates/FEDORA-2023-f61fbd10ad FEDORA-2023-f489ae7291 has been submitted as an update to Fedora 38. https://bodhi.fedoraproject.org/updates/FEDORA-2023-f489ae7291 FEDORA-2023-f489ae7291 has been pushed to the Fedora 38 testing repository. You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-f489ae7291 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates. FEDORA-2023-f61fbd10ad has been pushed to the Fedora 37 testing repository. Soon you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-f61fbd10ad` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-f61fbd10ad See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates. FEDORA-2023-f489ae7291 has been pushed to the Fedora 38 stable repository. If problem still persists, please make note of it in this bug report. FEDORA-2023-f61fbd10ad has been pushed to the Fedora 37 stable repository. If problem still persists, please make note of it in this bug report. |