mirror of
https://github.com/curl/curl.git
synced 2026-04-24 06:22:11 +03:00
hostip.c: fix leak of addrinfo
When creating a dns entry, the addrinfo is passed into the entry on success and needed deallocation by the caller on failure. Change the signature to have Curl_dnscache_mk_entry() *always* take ownership of the addrinfo, even on failure. Change parameter to address of pointer so that call always clears it. This makes the handling of failures to Curl_dnscache_mk_entry() simpler. Fixes #20465 Closes #20468
This commit is contained in:
parent
a84b041281
commit
ffdbc04c7b
5 changed files with 24 additions and 27 deletions
|
|
@ -332,14 +332,13 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
|
|||
result = ares->result;
|
||||
if(ares->ares_status == ARES_SUCCESS && !result) {
|
||||
data->state.async.dns =
|
||||
Curl_dnscache_mk_entry(data, ares->temp_ai,
|
||||
Curl_dnscache_mk_entry(data, &ares->temp_ai,
|
||||
data->state.async.hostname, 0,
|
||||
data->state.async.port, FALSE);
|
||||
if(!data->state.async.dns) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
ares->temp_ai = NULL; /* temp_ai now owned by entry */
|
||||
#ifdef HTTPSRR_WORKS
|
||||
{
|
||||
struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo);
|
||||
|
|
|
|||
|
|
@ -604,10 +604,9 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
|
|||
|
||||
if(thrdd->addr->res) {
|
||||
data->state.async.dns =
|
||||
Curl_dnscache_mk_entry(data, thrdd->addr->res,
|
||||
Curl_dnscache_mk_entry(data, &thrdd->addr->res,
|
||||
data->state.async.hostname, 0,
|
||||
data->state.async.port, FALSE);
|
||||
thrdd->addr->res = NULL;
|
||||
if(!data->state.async.dns)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
|
|
|
|||
|
|
@ -1253,7 +1253,8 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
|||
goto error;
|
||||
|
||||
/* we got a response, create a dns entry. */
|
||||
dns = Curl_dnscache_mk_entry(data, ai, dohp->host, 0, dohp->port, FALSE);
|
||||
dns = Curl_dnscache_mk_entry(data, &ai, dohp->host, 0,
|
||||
dohp->port, FALSE);
|
||||
if(dns) {
|
||||
/* Now add and HTTPSRR information if we have */
|
||||
#ifdef USE_HTTPSRR
|
||||
|
|
@ -1278,8 +1279,6 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
|||
result = Curl_dnscache_add(data, dns);
|
||||
*dnsp = data->state.async.dns;
|
||||
}
|
||||
else
|
||||
Curl_freeaddrinfo(ai);
|
||||
} /* address processing done */
|
||||
|
||||
/* All done */
|
||||
|
|
|
|||
35
lib/hostip.c
35
lib/hostip.c
|
|
@ -559,20 +559,20 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
|
|||
|
||||
struct Curl_dns_entry *
|
||||
Curl_dnscache_mk_entry(struct Curl_easy *data,
|
||||
struct Curl_addrinfo *addr,
|
||||
struct Curl_addrinfo **paddr,
|
||||
const char *hostname,
|
||||
size_t hostlen, /* length or zero */
|
||||
int port,
|
||||
bool permanent)
|
||||
{
|
||||
struct Curl_dns_entry *dns;
|
||||
struct Curl_dns_entry *dns = NULL;
|
||||
|
||||
#ifndef CURL_DISABLE_SHUFFLE_DNS
|
||||
/* shuffle addresses if requested */
|
||||
if(data->set.dns_shuffle_addresses) {
|
||||
CURLcode result = Curl_shuffle_addr(data, &addr);
|
||||
if(data->set.dns_shuffle_addresses && paddr) {
|
||||
CURLcode result = Curl_shuffle_addr(data, paddr);
|
||||
if(result)
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
(void)data;
|
||||
|
|
@ -583,10 +583,10 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
|
|||
/* Create a new cache entry */
|
||||
dns = curlx_calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
|
||||
if(!dns)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
dns->refcount = 1; /* the cache has the first reference */
|
||||
dns->addr = addr; /* this is the address(es) */
|
||||
dns->addr = paddr ? *paddr : NULL; /* this is the address(es) */
|
||||
if(permanent) {
|
||||
dns->timestamp.tv_sec = 0; /* an entry that never goes stale */
|
||||
dns->timestamp.tv_usec = 0; /* an entry that never goes stale */
|
||||
|
|
@ -598,13 +598,19 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
|
|||
if(hostlen)
|
||||
memcpy(dns->hostname, hostname, hostlen);
|
||||
|
||||
out:
|
||||
if(paddr) {
|
||||
if(!dns)
|
||||
Curl_freeaddrinfo(*paddr);
|
||||
*paddr = NULL;
|
||||
}
|
||||
return dns;
|
||||
}
|
||||
|
||||
static struct Curl_dns_entry *
|
||||
dnscache_add_addr(struct Curl_easy *data,
|
||||
struct Curl_dnscache *dnscache,
|
||||
struct Curl_addrinfo *addr,
|
||||
struct Curl_addrinfo **paddr,
|
||||
const char *hostname,
|
||||
size_t hlen, /* length or zero */
|
||||
int port,
|
||||
|
|
@ -615,7 +621,7 @@ dnscache_add_addr(struct Curl_easy *data,
|
|||
struct Curl_dns_entry *dns;
|
||||
struct Curl_dns_entry *dns2;
|
||||
|
||||
dns = Curl_dnscache_mk_entry(data, addr, hostname, hlen, port, permanent);
|
||||
dns = Curl_dnscache_mk_entry(data, paddr, hostname, hlen, port, permanent);
|
||||
if(!dns)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -627,7 +633,6 @@ dnscache_add_addr(struct Curl_easy *data,
|
|||
dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1,
|
||||
(void *)dns);
|
||||
if(!dns2) {
|
||||
dns->addr = NULL;
|
||||
dnscache_entry_free(dns);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -977,13 +982,9 @@ out:
|
|||
}
|
||||
else if(addr) {
|
||||
/* we got a response, create a dns entry, add to cache, return */
|
||||
dns = Curl_dnscache_mk_entry(data, addr, hostname, 0, port, FALSE);
|
||||
dns = Curl_dnscache_mk_entry(data, &addr, hostname, 0, port, FALSE);
|
||||
if(!dns || Curl_dnscache_add(data, dns)) {
|
||||
/* this is OOM or similar, do not store such negative resolves */
|
||||
Curl_freeaddrinfo(addr);
|
||||
if(dns)
|
||||
/* avoid a dangling pointer to addr in the dying dns entry */
|
||||
dns->addr = NULL;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
|
@ -1442,14 +1443,12 @@ err:
|
|||
}
|
||||
|
||||
/* put this new host in the cache */
|
||||
dns = dnscache_add_addr(data, dnscache, head, curlx_str(&source),
|
||||
dns = dnscache_add_addr(data, dnscache, &head, curlx_str(&source),
|
||||
curlx_strlen(&source), (int)port, permanent);
|
||||
if(dns)
|
||||
/* release the returned reference; the cache itself will keep the
|
||||
* entry alive: */
|
||||
dns->refcount--;
|
||||
else
|
||||
Curl_freeaddrinfo(head);
|
||||
|
||||
dnscache_unlock(data, dnscache);
|
||||
|
||||
|
|
|
|||
|
|
@ -151,13 +151,14 @@ void Curl_printable_address(const struct Curl_addrinfo *ip,
|
|||
* The entry is created with a reference count of 1.
|
||||
* Use `Curl_resolv_unlink()` to release your hold on it.
|
||||
*
|
||||
* The call takes ownership of `addr`and makes a copy of `hostname`.
|
||||
* The call takes ownership of `addr`, even in case of failure, and always
|
||||
* clears `*paddr`. It makes a copy of `hostname`.
|
||||
*
|
||||
* Returns entry or NULL on OOM.
|
||||
*/
|
||||
struct Curl_dns_entry *
|
||||
Curl_dnscache_mk_entry(struct Curl_easy *data,
|
||||
struct Curl_addrinfo *addr,
|
||||
struct Curl_addrinfo **paddr,
|
||||
const char *hostname,
|
||||
size_t hostlen, /* length or zero */
|
||||
int port,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue