The following code reliably results in a segfault in curl 7.60.0 on Linux (Linux 4.15.0-23-generic #25-Ubuntu SMP Wed May 23 18:02:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux):
$ curl -L https://github.com/curl/curl/releases/download/curl-7_60_0/curl-7.60.0.tar.gz | tar xvz
$ cd curl-7.60.0/
$ ./configure && make
$ gcc -o test test.c -Llib/.libs -lcurl
$ LD_LIBRARY_PATH=lib/.libs gdb ./test
(gdb) run
Starting program: test
Thread 1 "test" received signal SIGSEGV, Segmentation fault.
0x00007ffff7ba0c34 in process_pending_handles () from lib/.libs/libcurl.so.4
(gdb) bt
#0 0x00007ffff7ba0c34 in process_pending_handles () from lib/.libs/libcurl.so.4
#1 0x00007ffff7ba0d60 in multi_done () from lib/.libs/libcurl.so.4
#2 0x00007ffff7ba1248 in curl_multi_remove_handle () from lib/.libs/libcurl.so.4
#3 0x0000555555554b46 in main ()
The problems appears to occur because of the following:
The multi handle is configured to create at most 1 connection to a host.
Two easy handles are created to make a request to the same host.
The first handle grabs a connection and starts processing the request.
The second handle reaches the CURLM_STATE_CONNECT state but has no connections available, so it's added to the multi handle's list of connect-pending handles.
Before the first request completes, the second handle is removed from the multi handle. This doesn't remove the easy handle from the pending list. The handle is then freed, which leaves a freed entry on the pending list.
The first handle is removed from the multi handle. Because it has an associated connection, multi_done is called, which in turn calls process_pending_handles to dequeue the next handle waiting for a connection, segfaulting by accessing a freed entry.
Adding the following code to remove a handle from the connect-pending list in all cases seems to fix the issue:
*** a/multi.c 2018-05-07 02:18:03.000000000 -0700
--- b/multi.c 2018-06-21 17:31:56.248788436 -0700
***************
*** 698,703 ****
--- 698,708 ----
Curl_getoff_all_pipelines(data, data->easy_conn);
}
+ if(data->connect_queue.ptr)
+ /* the handle was on the pending list waiting for an available connection,
+ so go ahead and remove it */
+ Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache, *after* the possible
multi_done() call above */
The text was updated successfully, but these errors were encountered:
The following code reliably results in a segfault in curl 7.60.0 on Linux (
Linux 4.15.0-23-generic #25-Ubuntu SMP Wed May 23 18:02:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
):Steps to reproduce on Linux:
The problems appears to occur because of the following:
CURLM_STATE_CONNECT
state but has no connections available, so it's added to the multi handle's list of connect-pending handles.multi_done
is called, which in turn callsprocess_pending_handles
to dequeue the next handle waiting for a connection, segfaulting by accessing a freed entry.Adding the following code to remove a handle from the connect-pending list in all cases seems to fix the issue:
The text was updated successfully, but these errors were encountered: