curl-library
Use-after-free with libcurl+ares on windows?
Date: Thu, 04 Aug 2005 03:23:11 +0530
Hi All,
I am using libcurl 7.12.1 on Windows 2000 with the ares resolver. (I
know this is a fairly old version, but as of now I don't have an option
to do an immediate upgrade.)
I am seeing intermittent crashes in ares callbacks. It has been really
difficult to pin down a testcase since the application is a crawler that
does tens of thousands of requests against several hundred hosts in a
day. But, in general, the problem appears to be related somehow to
connect timeouts. I have been able to reproduce the problem under purify
much more frequently by reducing the value of CURLOPT_TIMEOUT to just
one sec. A typical instance of a purify report of the problem is attached.
It seems to me that what is happening is that there are some cases where
some ares query might outlive the connection data. This makes the
callback crash when it is fired since it ends up poking at already freed
data.
I really don't know much about the ares API and how ares is used in
curl. On a random hunch, I tried the following
diff -u -p -1 -0 -r1.4 url.c
--- url.c 14 Dec 2004 13:27:13 -0000 1.4
+++ url.c 3 Aug 2005 21:35:37 -0000
@@ -1494,20 +1494,24 @@ CURLcode Curl_disconnect(struct connectd
Curl_safefree(conn->allocptr.host);
Curl_safefree(conn->allocptr.cookiehost);
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) || \
defined(USE_THREADING_GETADDRINFO)
/* possible left-overs from the async name resolve */
Curl_safefree(conn->async.hostname);
Curl_safefree(conn->async.os_specific);
#endif
+#if defined(USE_ARES)
+ ares_cancel(conn->data->state.areschannel);
+#endif
+
Curl_free_ssl_config(&conn->ssl_config);
free(conn); /* free all the connection oriented data */
return CURLE_OK;
}
/*
* This function should return TRUE if the socket is to be assumed to
* be dead. Most commonly this happens when the server has closed the
This makes my application much more stable.
So, getting to the point .... I have lots of questions: Has anyone
encountered such a problem earlier? Has there been any work on a similar
issue in later versions of curl? Is my reasoning above sane? Does the my
"random hunch" patch above make any sense at all?
Harshal
[E] FMW: Free memory write in addrinfo_callback {1 occurrence}
Writing 1 byte to 0x09087884 (1 byte at 0x09087884 illegal)
Address 0x09087884 is 1908 bytes into a 1928 byte block at 0x09087110
Address 0x09087884 points to a malloc'd block in heap 0x04eb0000
Thread ID: 0x990
Error location
addrinfo_callback [hostasyn.c:118]
struct connectdata *conn = (struct connectdata *)arg;
struct Curl_dns_entry *dns = NULL;
=> conn->async.done = TRUE;
conn->async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
Curl_addrinfo4_callback [hostasyn.c:158]
end_hquery [ares_gethostbyname.c:150]
host_callback [ares_gethostbyname.c:139]
qcallback [ares_query.c:108]
end_query [ares_process.c:620]
process_answer [ares_process.c:352]
read_udp_packets [ares_process.c:266]
ares_process [ares_process.c:72]
Curl_is_resolved [hostares.c:148]
curl_multi_perform [multi.c:393]
struct Curl_dns_entry *dns = NULL;
/* check if we have the name resolved by now */
=> easy->result = Curl_is_resolved(easy->easy_conn, &dns);
if(dns) {
/* Perform the next step in the connection phase, and then move on
CurlMultiPageFetcher::run(void) [curlmultipagefetcher.cpp:541]
Thread [_thread.cpp:76]
threadstart [thread.c:196]
Allocation location
malloc [dbgheap.c:138]
CreateConnection [url.c:2153]
Curl_connect [url.c:3434]
curl_multi_perform [multi.c:373]
CurlMultiPageFetcher::run(void) [curlmultipagefetcher.cpp:495]
Thread [_thread.cpp:76]
threadstart [thread.c:196]
Free location
free [dbgheap.c:1024]
Curl_disconnect [url.c:1510]
ConnectionKillOne [url.c:1686]
ConnectionStore [url.c:1714]
CreateConnection [url.c:3167]
Curl_connect [url.c:3434]
curl_multi_perform [multi.c:373]
/* Connect. We get a connection identifier filled in. */
Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
=> &async);
if(CURLE_OK == easy->result) {
if(async)
Received on 2005-08-04