Bug 2172377 - Crash under Curl_fillreadbuffer()
Summary: Crash under Curl_fillreadbuffer()
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: syncevolution
Version: 37
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Milan Crha
QA Contact: Fedora Extras Quality Assurance
URL: https://retrace.fedoraproject.org/faf...
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2023-02-22 07:10 UTC by Milan Crha
Modified: 2023-03-12 00:41 UTC (History)
9 users (show)

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:
Clone Of:
Environment:
Last Closed: 2023-03-11 03:13:15 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Milan Crha 2023-02-22 07:10:53 UTC
This had been opened on the SyncEvolution mailing list:
https://lists.freedesktop.org/archives/syncevolution/2023-February/000778.html

And I can reproduce it too, by running:

   $ gdb syncevolution --ex "r --daemon=no --run --sync refresh-from-local memotoo"

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.

I can share credentials for the memotoo test account in private, if needed, to make it easier for you to reproduce.

Packages installed:
   curl-7.85.0-6.fc37.x86_64
   curl-debuginfo-7.85.0-6.fc37.x86_64
   curl-debugsource-7.85.0-6.fc37.x86_64
   curl-minimal-debuginfo-7.85.0-6.fc37.x86_64
   libcurl-7.85.0-6.fc37.x86_64
   libcurl-debuginfo-7.85.0-6.fc37.x86_64
   libcurl-devel-7.85.0-6.fc37.x86_64
   libcurl-minimal-debuginfo-7.85.0-6.fc37.x86_64
   syncevolution-2.0.0-5.fc37.x86_64
   syncevolution-debuginfo-2.0.0-5.fc37.x86_64
   syncevolution-debugsource-2.0.0-5.fc37.x86_64
   syncevolution-gtk-2.0.0-5.fc37.x86_64
   syncevolution-libs-2.0.0-5.fc37.x86_64

Backtrace:

Thread 1 "syncevolution" received signal SIGSEGV, Segmentation fault.
0x00007ffff6fc5d70 in ?? () from /lib64/libcurl.so.4
(gdb) bt full
#0  0x00007ffff6fc5d70 in  () at /lib64/libcurl.so.4
#1  0x00007ffff6f9aa2d in Curl_fillreadbuffer (data=data@entry=0x55555682dd80, bytes=<optimized out>, nreadp=nreadp@entry=0x7fffffffbae0) at ../../lib/transfer.c:235
        buffersize = 65536
        nread = <optimized out>
        readfunc = <optimized out>
        extra_data = <optimized out>
#2  0x00007ffff6f9cb63 in readwrite_upload (didwhat=<synthetic pointer>, conn=0x5555568590d0, data=0x55555682dd80) at ../../lib/transfer.c:995
        fillcount = 140737337116468
        http = <optimized out>
        nbody = <optimized out>
        offset = <optimized out>
        i = <optimized out>
        si = <optimized out>
        bytes_written = 140737337116468
        sending_http_headers = false
        k = 0x55555682de58
        result = <optimized out>
        nread = <optimized out>
        k = 0x55555682de58
        result = <optimized out>
        didwhat = 2
        fd_read = <optimized out>
        fd_write = <optimized out>
        select_res = <optimized out>
#3  Curl_readwrite (conn=0x5555568590d0, data=0x55555682dd80, done=<optimized out>, comeback=<optimized out>) at ../../lib/transfer.c:1228
        k = 0x55555682de58
        result = <optimized out>
        didwhat = 2
        fd_read = <optimized out>
        fd_write = <optimized out>
        select_res = <optimized out>
#4  0x00007ffff6f833b7 in multi_runsingle (multi=multi@entry=0x555556871530, nowp=nowp@entry=0x7fffffffbc50, data=data@entry=0x55555682dd80) at ../../lib/multi.c:2406
        newurl = 0x0
        retry = false
        comeback = false
        stream_error = false
        msg = <optimized out>
        connected = true
        async = false
        protocol_connected = true
        dophase_done = true
        done = false
        rc = CURLM_OK
        result = CURLE_OK
        recv_timeout_ms = <optimized out>
        send_timeout_ms = <optimized out>
        control = -148505776
#5  0x00007ffff6f85c5e in curl_multi_perform (multi=0x555556871530, running_handles=0x7fffffffbd58) at ../../lib/multi.c:2684
        result = <optimized out>

                  pipe_st = {old_pipe_act = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, sa_mask = {__val = {4096, 140737339849552, 4096, 140737339849552, 4096, 140737339849552, 4096, 140737339849552, 4096, 140737339849552, 4096, 0, 0, 140737353902508, 1, 93825012274480}}, sa_flags = 335544320, sa_restorer = 0x7ffff725fb50 <__restore_rt>}, no_signal = false}
        data = 0x55555682dd80
        returncode = CURLM_OK
        t = 0x0
        now = {tv_sec = 3756, tv_usec = 630007}
#6  0x00007ffff6f5c20b in easy_transfer (multi=<optimized out>) at ../../lib/easy.c:662
        still_running = 0
        done = <optimized out>
        mcode = <optimized out>
        result = CURLE_OK
        multi = 0x555556871530
        mcode = <optimized out>
        result = CURLE_OK

                  pipe_st = {old_pipe_act = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, sa_mask = {__val = {4096, 140737488338080, 2016, 336, 101, 140737337106184, 33, 140737488338128, 140737340260206, 140737341516928, 93825012171832, 140737353902508, 93825011998080, 93, 0, 93825011998080}}, sa_flags = 335544320, sa_restorer = 0x7ffff725fb50 <__restore_rt>}, no_signal = false}
#7  easy_perform (events=false, data=0x55555682dd80) at ../../lib/easy.c:752
        multi = 0x555556871530
        mcode = <optimized out>
        result = CURLE_OK

                  pipe_st = {old_pipe_act = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, sa_mask = {__val = {4096, 140737488338080, 2016, 336, 101, 140737337106184, 33, 140737488338128, 140737340260206, 140737341516928, 93825012171832, 140737353902508, 93825011998080, 93, 0, 93825011998080}}, sa_flags = 335544320, sa_restorer = 0x7ffff725fb50 <__restore_rt>}, no_signal = false}
#8  curl_easy_perform (data=0x55555682dd80) at ../../lib/easy.c:771
#9  0x00007ffff7cca155 in SyncEvo::CurlTransportAgent::send(char const*, unsigned long) (this=0x555555de3000, data=<optimized out>, len=11328) at src/syncevo/CurlTransportAgent.cpp:211
        code = <optimized out>
        contentHeader = "Content-Type: application/vnd.syncml+wbxml"
#10 0x00007ffff7d81d58 in SyncEvo::SyncContext::doSync() (this=0x5555555eab90) at src/syncevo/SyncContext.cpp:4224
        sessionKey = std::shared_ptr<sysync::KeyType> (empty) = {get() = 0x0}
Python Exception <class 'gdb.error'>: value has been optimized out
        signalGuard = 
        catchSignals = <optimized out>
        delay = <optimized out>
        flags = <optimized out>
        status = SyncEvo::STATUS_OK
        s = "application/vnd.syncml+wbxml"
        xml = ""
        configname = ""
        targets = std::shared_ptr<sysync::KeyType> (use count 1, weak count 0) = {get() = 0x5555567f9590}
        target = std::shared_ptr<sysync::KeyType> (empty) = {get() = 0x0}
        progressInfo = {eventtype = 6, targetID = 0, extra1 = 0, extra2 = 0, extra3 = 0}
        stepCmd = 110
        session = std::shared_ptr<sysync::SessionType> (use count 3, weak count 0) = {get() = 0x55555682f2a0}
        sendBuffer = {<boost::shared_array<char>> = {px = 0x7fffda10d010 "\002\244\001j", pn = {pi_ = 0x5555568548d0}}, m_size = 11328}
        sessionSentinel = std::unique_ptr<SyncEvo::SyncContext::SessionSentinel> = {get() = <optimized out>}
        aborting = <optimized out>
        suspending = <optimized out>
        sendStart = {<timespec> = {tv_sec = 3755, tv_nsec = 723905008}, <No data fields>}
        resendStart = {<timespec> = {tv_sec = 3755, tv_nsec = 723905008}, <No data fields>}
        requestNum = <optimized out>
        previousStepCmd = 10
Python Exception <class 'gdb.error'>: value has been optimized out
        numItemsReceived = 
#11 0x00007ffff7d7ca68 in SyncEvo::SyncContext::sync(SyncEvo::SyncReport*) (this=0x5555555eab90, report=0x7fffffffd288) at src/syncevo/SyncContext.cpp:3396
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'

                  dummy = {_vptr.SyncConfig = 0x7ffff7efca20 <vtable for SyncEvo::SyncConfig+16>, m_peer = "", m_peerPath = "volatile", m_contextPath = "volatile", m_layout = SyncEvo::SyncConfig::HTTP_SERVER_LAYOUT, m_redirectPeerRootPath = "", m_configWriteMode = SyncEvo::SyncConfig::MIGRATE_AUTOMATICALLY, m_ephemeral = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_tree = std::shared_ptr<class SyncEvo::ConfigTree> (use count 1, weak count 0) = {get() = 0x555556721100}, m_fileTree = std::shared_ptr<class SyncEvo::FileConfigTree> (empty) = {get() = 0x0}, m_globalNode = std::shared_ptr<class SyncEvo::FilterConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}, m_globalHiddenNode = std::shared_ptr<class SyncEvo::ConfigNode> (empty) = {get() = 0x0}, m_contextNode = std::shared_ptr<class SyncEvo::FilterConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}, m_contextHiddenNode = std::shared_ptr<class SyncEvo::ConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}, m_peerNode = std::shared_ptr<class SyncEvo::FilterConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}, m_hiddenPeerNode = std::shared_ptr<class SyncEvo::ConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}, m_props = {std::shared_ptr<class SyncEvo::FilterConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}, std::shared_ptr<class SyncEvo::FilterConfigNode> (use count 7, weak count 0) = {get() = 0x555556734d40}}, m_sourceFilters = {<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, SyncEvo::ConfigProps, SyncEvo::Nocase<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, SyncEvo::ConfigProps> > >> = std::map with 0 elements, <No data fields>}, m_nodeCache = std::map with 4 elements}
        activeSources = std::set with 4 elements = {[0] = "addressbook", [1] = "calendar", [2] = "memo", [3] = "todo"}
        startSourceAccess = {__this = 0x5555555eab90}
        url = "http://sync.memotoo.com/syncML"
        swapengine = {m_client = @0x5555555eab90, m_oldengine = {m_engine = std::shared_ptr<class sysync::TEngineModuleBase> (use count 1, weak count 0) = {get() = 0x0}}}
        status = SyncEvo::STATUS_OK
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'

                  sourceList = {<std::vector<SyncEvo::SyncSource*, std::allocator<SyncEvo::SyncSource*> >> = std::vector of length 4, capacity 4 = {0x5555567212e0, 0x555556726230, 0x55555672b0d0, 0x55555672fee0}, m_virtualSources = std::vector of length 0, capacity 0, m_logdir = std::shared_ptr<class SyncEvo::LogDir> (use count 1, weak count 2) = {get() = 0x5555555d8ee0}, m_client = @0x5555555eab90, m_prepared = std::set with 0 elements, m_intro = "", m_doLogging = true, m_reportTodo = true, m_logLevel = SyncEvo::SourceList::LOGGING_FULL, m_previousLogdir = "/home/mcrha/.cache/syncevolution/memotoo-2023-02-22-07-53"}
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'

                  buffer = {<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, SyncEvo::SyncSourceReport, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, SyncEvo::SyncSourceReport> > >> = std::map with 0 elements, m_start = 0, m_end = 0, m_status = SyncEvo::STATUS_OK, m_error = "", m_localName = "LOCAL", m_remoteName = "REMOTE"}
        syncSentinel = {m_oldContext = 0x0}
#12 0x00007ffff7d15b7e in SyncEvo::Cmdline::run() (this=this@entry=0x7fffffffd240) at src/syncevo/Cmdline.cpp:1707
        unmatchedSources = std::set with 0 elements
        context = std::shared_ptr<SyncEvo::SyncContext> (use count 1, weak count 0) = {get() = 0x5555555eab90}
#13 0x0000555555560ce3 in SyncEvo::main(int, char**) (argc=<optimized out>, argv=<optimized out>) at src/syncevolution.cpp:467
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'
Python Exception <class 'AttributeError'>: 'NoneType' object has no attribute 'pointer'

                      cmdline = {<SyncEvo::Cmdline> = {_vptr.Cmdline = 0x5555555834d8 <vtable for SyncEvo::KeyringSyncCmdline+16>, m_args = std::vector of length 0, capacity 0, m_argc = 6, m_argv = 0x7fffffffda28, m_argvArray = std::vector of length 0, capacity 0, m_report = {<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, SyncEvo::SyncSourceReport, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, SyncEvo::SyncSourceReport> > >> = std::map with 0 elements, m_start = 1677049095, m_end = 0, m_status = SyncEvo::STATUS_OK, m_error = "", m_localName = "LOCAL", m_remoteName = "REMOTE"}, m_quiet = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_dryrun = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_status = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_version = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_usage = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_configure = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_remove = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_run = {<SyncEvo::InitStateBase<bool, false>> = {m_value = true}, m_wasSet = true}, m_migrate = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_printDatabases = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_createDatabase = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_removeDatabase = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_printServers = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_printTemplates = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_printConfig = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_printSessions = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_dontrun = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_monitor = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_useDaemon = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = true}, m_props = {<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, SyncEvo::ContextProps, SyncEvo::Nocase<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, SyncEvo::ContextProps> > >> = std::map with 1 element, <No data fields>}, m_validSyncProps = @0x7ffff7f06b30, m_validSourceProps = @0x7ffff7f073c0, m_restore = "", m_before = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_after = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_accessItems = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_itemPath = "", m_delimiter = "\n\n", m_luids = empty std::__cxx11::list, m_printItems = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_update = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_import = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_export = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_deleteItems = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}, m_server = "memotoo", m_template = "", m_sources = std::set with 0 elements, m_configModified = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = false}}, <No data fields>}
        parsedArgs = std::vector of length 6, capacity 8 = {"/usr/bin/syncevolution", "--daemon=no", "--run", "--sync", "refresh-from-local", "memotoo"}
        useDaemon = {<SyncEvo::InitStateBase<bool, false>> = {m_value = false}, m_wasSet = true}

                      redirect = {<boost::noncopyable_::noncopyable> = {<boost::noncopyable_::base_token> = {<No data fields>}, <No data fields>}, m_logger = {m_logger = std::shared_ptr<class SyncEvo::Logger> (use count 3, weak count 0) = {get() = 0x5555555a2850}}}
        exe = <optimized out>

Comment 1 Kamil Dudka 2023-02-23 14:50:40 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.

Comment 2 Milan Crha 2023-02-23 16:10:51 UTC
(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.

Comment 3 Kamil Dudka 2023-02-28 08:34:52 UTC
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]

Comment 4 Milan Crha 2023-02-28 09:25:28 UTC
Thank you for the detailed information. I'm moving this to the syncevolution and will let the upstream folks know.

Comment 5 Patrick Ohly 2023-02-28 11:44:08 UTC
> 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?

Comment 6 Kamil Dudka 2023-02-28 12:16:59 UTC
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

Comment 7 Kamil Dudka 2023-02-28 12:40:11 UTC
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)) ||

Comment 8 Lukáš Zaoral 2023-03-02 08:22:01 UTC
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

Comment 9 Patrick Ohly 2023-03-02 15:47:34 UTC
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.

Comment 10 Milan Crha 2023-03-02 17:02:36 UTC
(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).

Comment 11 Patrick Ohly 2023-03-02 17:30:58 UTC
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.

Comment 12 Milan Crha 2023-03-03 07:22:57 UTC
Right, I'm building an update now. The bug will be updated when it's ready.

Comment 13 Fedora Update System 2023-03-03 07:44:59 UTC
FEDORA-2023-f61fbd10ad has been submitted as an update to Fedora 37. https://bodhi.fedoraproject.org/updates/FEDORA-2023-f61fbd10ad

Comment 14 Fedora Update System 2023-03-03 11:26:28 UTC
FEDORA-2023-f489ae7291 has been submitted as an update to Fedora 38. https://bodhi.fedoraproject.org/updates/FEDORA-2023-f489ae7291

Comment 15 Fedora Update System 2023-03-04 02:34:44 UTC
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.

Comment 16 Fedora Update System 2023-03-04 03:09:36 UTC
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.

Comment 17 Fedora Update System 2023-03-11 03:13:15 UTC
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.

Comment 18 Fedora Update System 2023-03-12 00:41:00 UTC
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.


Note You need to log in before you can comment on or make changes to this bug.